• on a (racket) procedure for reading an article from stdin

    From Julieta Shem@21:1/5 to All on Mon Dec 25 22:24:04 2023
    Here's a procedure for reading lines from the stdin. It implements the handling of a POST command from NNTP. It seems to work, but it looks
    like work from a beginner. I wonder if there's anything you can say to illuminate me.

    What does it do? A thread will kill the program if the user takes too
    long. (Otherwise we kill the thread.) The reading ends gracefully if
    the user types a ``.'' on a line by itself. Otherwise we append the
    current line read onto the end of a LINES-SO-FAR list and repeat. (Yes,
    if a ``..'' is on a line by itself, that's the user escaping the dot
    that's not the end of input. I decided to implement this corner-case
    with that /let/ before repeating.)

    (define (read-with-timeout [lines-so-far '()] [timeout 60])
    (define killer
    (thread (lambda ()
    (sleep timeout)
    (displayln "Timeout on posting article.")
    (flush-output)
    (exit))))
    (define ln (read-line (current-input-port) 'return-linefeed))
    (kill-thread killer)
    (cond
    [(eof-object? ln)
    (displayln "fatal: eof while reading article...")
    (exit)]
    [(string=? ln ".")
    (string-join lines-so-far "\r\n")]
    [else
    (let ([ln (if (string=? ln "..") "." ln)])
    (read-with-timeout (append lines-so-far (list ln))))]))

    Any thoughts, comments? Help to be a better Lisp programmer.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Julieta Shem on Tue Dec 26 04:59:52 2023
    On 2023-12-26, Julieta Shem <jshem@yaxenu.org> wrote:
    Here's a procedure for reading lines from the stdin. It implements the handling of a POST command from NNTP. It seems to work, but it looks
    like work from a beginner. I wonder if there's anything you can say to illuminate me.

    What does it do? A thread will kill the program if the user takes too
    long. (Otherwise we kill the thread.) The reading ends gracefully if
    the user types a ``.'' on a line by itself. Otherwise we append the
    current line read onto the end of a LINES-SO-FAR list and repeat. (Yes,
    if a ``..'' is on a line by itself, that's the user escaping the dot
    that's not the end of input. I decided to implement this corner-case
    with that /let/ before repeating.)

    (define (read-with-timeout [lines-so-far '()] [timeout 60])
    (define killer
    (thread (lambda ()
    (sleep timeout)
    (displayln "Timeout on posting article.")
    (flush-output)
    (exit))))
    (define ln (read-line (current-input-port) 'return-linefeed))
    (kill-thread killer)
    (cond
    [(eof-object? ln)
    (displayln "fatal: eof while reading article...")
    (exit)]
    [(string=? ln ".")
    (string-join lines-so-far "\r\n")]
    [else
    (let ([ln (if (string=? ln "..") "." ln)])
    (read-with-timeout (append lines-so-far (list ln))))]))

    Any thoughts, comments? Help to be a better Lisp programmer.

    Using a thread just for timing out a read is ugly, like something you'd
    do in a shell program, not in a serious application.

    (And if the shell is Bash, you wouldn't have to; it has a timed out read!
    Type "help read" in bash: you can see that read can read characters
    up to a specified delimiter, with a timeout (-t)).

    A proper Unix program uses select or poll, or else uses setsockopt
    to set up read timeout (if the input is known to be a socket).

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Kaz Kylheku on Tue Dec 26 12:25:11 2023
    Kaz Kylheku <433-929-6894@kylheku.com> writes:

    On 2023-12-26, Julieta Shem <jshem@yaxenu.org> wrote:
    Here's a procedure for reading lines from the stdin. It implements the
    handling of a POST command from NNTP. It seems to work, but it looks
    like work from a beginner. I wonder if there's anything you can say to
    illuminate me.

    What does it do? A thread will kill the program if the user takes too
    long. (Otherwise we kill the thread.) The reading ends gracefully if
    the user types a ``.'' on a line by itself. Otherwise we append the
    current line read onto the end of a LINES-SO-FAR list and repeat. (Yes,
    if a ``..'' is on a line by itself, that's the user escaping the dot
    that's not the end of input. I decided to implement this corner-case
    with that /let/ before repeating.)

    (define (read-with-timeout [lines-so-far '()] [timeout 60])
    (define killer
    (thread (lambda ()
    (sleep timeout)
    (displayln "Timeout on posting article.")
    (flush-output)
    (exit))))
    (define ln (read-line (current-input-port) 'return-linefeed))
    (kill-thread killer)
    (cond
    [(eof-object? ln)
    (displayln "fatal: eof while reading article...")
    (exit)]
    [(string=? ln ".")
    (string-join lines-so-far "\r\n")]
    [else
    (let ([ln (if (string=? ln "..") "." ln)])
    (read-with-timeout (append lines-so-far (list ln))))]))

    Any thoughts, comments? Help to be a better Lisp programmer.

    Using a thread just for timing out a read is ugly, like something you'd
    do in a shell program, not in a serious application.

    (And if the shell is Bash, you wouldn't have to; it has a timed out read! Type "help read" in bash: you can see that read can read characters
    up to a specified delimiter, with a timeout (-t)).

    A proper Unix program uses select or poll, or else uses setsockopt
    to set up read timeout (if the input is known to be a socket).

    In C I would have used select. But how do I select in Racket? I found Racket's sync/timeout, a procedure based on Racket's ``events''. The
    reference dissertates briefly about events at

    https://docs.racket-lang.org/reference/sync.html

    and they cite

    John H. Reppy, Concurrent Programming in ML, Cambridge University
    Press, 1999. https://doi.org/10.1017/CBO9780511574962

    as a reference. It's unclear to me that this is what I'm looking for,
    but it might very well be.

    --8<---------------cut here---------------start------------->8---
    #lang racket/base
    (define (read-line-timeout [timeout 60] [port (current-input-port)])
    (define port-or-false
    (sync/timeout timeout port))
    (and port-or-false (read-line port-or-false)))

    (define (interact-with-timeout timeout)
    (define ln (read-line-timeout timeout))
    (cond [(not ln)
    (say "> God, you're slow.")]
    [(eof-object? ln)
    (say "> Okay, see you later.")]
    [else
    (say (format "< ~a" ln))
    (say "> But why do you say that?")
    (interact-with-timeout timeout)]))

    (define (say s) (displayln s) (flush-output))

    (module+ main
    (say "> Hello. Say anything and press RET.")
    (interact-with-timeout 3))
    --8<---------------cut here---------------end--------------->8---

    I see to see a complicated behavior of this program in Windows ``Command Prompt'', but not in the GNU EMACS eshell. On the Command Prompt,
    sometimes the timeout doesn't take effect. To make it easy to hit
    reproduce, I reduce the timeout to 1. Here's an example. I took way
    longer than 1 second to type that ``123''. The timeout only took effect
    on the second wait. Weird.

    c:\something>racket timezup.rkt
    Hello. Say anything and press RET.
    123
    < 123
    But why do you say that?
    God, you're slow.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Julieta Shem on Tue Dec 26 14:27:14 2023
    Julieta Shem <jshem@yaxenu.org> writes:

    [...]

    I see to see a complicated behavior of this program in Windows ``Command Prompt'', but not in the GNU EMACS eshell. On the Command Prompt,
    sometimes the timeout doesn't take effect. To make it easy to hit
    reproduce, I reduce the timeout to 1. Here's an example. I took way
    longer than 1 second to type that ``123''. The timeout only took effect
    on the second wait. Weird.

    c:\something>racket timezup.rkt
    Hello. Say anything and press RET.
    123
    < 123
    But why do you say that?
    God, you're slow.

    Here's a better presentation. I set the timeout to 1 second. After
    about ten seconds, I wrote ``No timeout'' and pressed RET.

    --8<---------------cut here---------------start------------->8--- c:\something>c:/sys/emacs/usr/mingw/usr/bin/time.exe racket timezup.rkt
    Hello. Say anything and press RET.
    No timeout.
    < No timeout.
    But why do you say that?
    God, you're slow.
    0.00user 0.00system 0:11.68elapsed 0%CPU (0avgtext+0avgdata 5228maxresident)k 0inputs+0outputs (1389major+0minor)pagefaults 0swaps
    --8<---------------cut here---------------end--------------->8---

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Julieta Shem on Fri Dec 29 02:19:44 2023
    On Tue, 26 Dec 2023 12:25:11 -0300, Julieta Shem wrote:

    https://docs.racket-lang.org/reference/sync.html

    I had a look at that. Why do languages feel they have to stack on thick
    layers of extra abstraction on top of basic POSIX concepts?

    I do more Python than Lisp, and look how thin Python’s standard-library abstractions on top of select/poll are: <https://docs.python.org/3/library/select.html>. Makes it so much easier
    to figure out what’s going on.

    I suppose Racket could be worse. It could be Java.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Lawrence D'Oliveiro on Fri Dec 29 00:09:19 2023
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Tue, 26 Dec 2023 12:25:11 -0300, Julieta Shem wrote:

    https://docs.racket-lang.org/reference/sync.html

    I had a look at that. Why do languages feel they have to stack on thick layers of extra abstraction on top of basic POSIX concepts?

    That seems to be the wrong thing to do for people who know the POSIX
    concepts. I believe the Racket people want to create their own world
    from scratch.

    I do more Python than Lisp, and look how thin Python’s standard-library abstractions on top of select/poll are: <https://docs.python.org/3/library/select.html>. Makes it so much easier
    to figure out what’s going on.

    True.

    I suppose Racket could be worse. It could be Java.

    Yes! Way worse.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Julieta Shem on Fri Dec 29 00:21:20 2023
    Julieta Shem <jshem@yaxenu.org> writes:

    Julieta Shem <jshem@yaxenu.org> writes:

    [...]

    I see to see a complicated behavior of this program in Windows ``Command
    Prompt'', but not in the GNU EMACS eshell. On the Command Prompt,
    sometimes the timeout doesn't take effect. To make it easy to hit
    reproduce, I reduce the timeout to 1. Here's an example. I took way
    longer than 1 second to type that ``123''. The timeout only took effect
    on the second wait. Weird.

    c:\something>racket timezup.rkt
    Hello. Say anything and press RET.
    123
    < 123
    But why do you say that?
    God, you're slow.

    Here's a better presentation. I set the timeout to 1 second. After
    about ten seconds, I wrote ``No timeout'' and pressed RET.

    c:\something>c:/sys/emacs/usr/mingw/usr/bin/time.exe racket timezup.rkt
    Hello. Say anything and press RET.
    No timeout.
    < No timeout.
    But why do you say that?
    God, you're slow.
    0.00user 0.00system 0:11.68elapsed 0%CPU (0avgtext+0avgdata 5228maxresident)k 0inputs+0outputs (1389major+0minor)pagefaults 0swaps

    This happens to be a known problem on Windows.

    https://github.com/racket/racket/issues/4728

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From George Neuner@21:1/5 to ldo@nz.invalid on Fri Dec 29 00:50:32 2023
    On Fri, 29 Dec 2023 02:19:44 -0000 (UTC), Lawrence D'Oliveiro
    <ldo@nz.invalid> wrote:

    On Tue, 26 Dec 2023 12:25:11 -0300, Julieta Shem wrote:

    https://docs.racket-lang.org/reference/sync.html

    I had a look at that. Why do languages feel they have to stack on thick >layers of extra abstraction on top of basic POSIX concepts?

    For one thing, because Windows is not POSIX compliant. Languages that
    try to be cross-platform have to do *something* to hide the
    differences.

    Whether you like the choices made by the implementors is a different
    matter. ;-)


    I do more Python than Lisp, and look how thin Python’s standard-library >abstractions on top of select/poll are: ><https://docs.python.org/3/library/select.html>. Makes it so much easier
    to figure out what’s going on.

    Agreed, Python does a better job of looking like POSIX. However, in
    1989 Guido had the benefit of (at least) POSIX.1 when he began to
    develop Python. And as "dictator for life", it was easy to add things
    when he thought they were needed.

    Although the Racket project technically began in 2015, it grew out of
    "PLT Scheme" which began in 1994. Scheme itself goes back to 1973 -
    far before POSIX to a time when things like GUIs, modular programming, networking, asynchronous I/O, threading, etc. were much less
    important.

    As a Scheme, PLT was hampered by compatibility concerns with a
    language from the 1970s.


    That's part of the reason the PLT group began Racket. Racket actually
    is not a Scheme but rather is a unique language that syntactically
    resembles Scheme and has similar (but greater) functionality.

    Racket, in fact, supports readers (as in Lisp) with more or less
    arbitrary parsing ability. If you are ambitous, you can create your
    own DSL language having any syntax you like ... as long as it can
    compile to Racket, it can be intermixed with Racket or with code from
    any of a number of other DSLs that are available.

    The Racket group currently is developing a new surface syntax -
    tentatively called "Rhombus" - which will be more conventional infix
    syntax. However, it still will be Racket underneath, so Racket and
    Rhombus code will be able to be intermixed.


    I suppose Racket could be worse. It could be Java.

    As a technical matter the JVM isn't bad ... it's only the Java
    language that sucks. But there are compilers for many languages that
    target the JVM, and most can interface to Java code if necessary. You
    can code for JVM in Lisp or Scheme if you want to.


    But Racket handles cross-platform quite nicely. Programs have to be
    recompiled with the native compiler of course, but as long as they
    don't use any non-Racket C libraries, they will be 100% *source*
    portable and almost everything will just work.
    [Windows and Linux return different native error codes, and of course
    there is the CR/LF problem, but Racket can identify the host system
    and it is pretty easy to write portable code - including GUI code -
    that will run on either system.]

    Current versions of Racket actually are built on Chez Scheme, and
    there is a (somewhat customized) Chez runtime underneath. Using
    Racket's foreign function interface (FFI) you can drop into Chez, or
    into C, or into any language that supports being called from C.

    With some restrictions, Racket itself supports being called from C, so
    it is possible for a C program to embed a Racket instance to use
    Racket libraries or even run a whole Racket program (in parallel if
    the Racket instance is executed in a C thread).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to George Neuner on Fri Dec 29 06:04:52 2023
    On Fri, 29 Dec 2023 00:50:32 -0500, George Neuner wrote:

    ... Windows is not POSIX compliant.

    Wasn’t NT supposed to be POSIX-compliant in the beginning? Seems like that whole part of the system has bitrotted away ...

    So you have to ask yourself: is your return from supporting Windows users
    worth the greatly increased expense?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From George Neuner@21:1/5 to ldo@nz.invalid on Fri Dec 29 10:54:14 2023
    On Fri, 29 Dec 2023 06:04:52 -0000 (UTC), Lawrence D'Oliveiro
    <ldo@nz.invalid> wrote:

    On Fri, 29 Dec 2023 00:50:32 -0500, George Neuner wrote:

    ... Windows is not POSIX compliant.

    Wasn’t NT supposed to be POSIX-compliant in the beginning? Seems like that >whole part of the system has bitrotted away ...

    Not exactly. NT's "POSIX support" was to add limited signal
    capability. Adopting the POSIX function APIs was never even
    considered.

    So you have to ask yourself: is your return from supporting Windows users >worth the greatly increased expense?

    More people directly use Windows than directly use Unix/Linux.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to George Neuner on Fri Dec 29 13:52:41 2023
    George Neuner <gneuner2@comcast.net> writes:

    On Fri, 29 Dec 2023 02:19:44 -0000 (UTC), Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    On Tue, 26 Dec 2023 12:25:11 -0300, Julieta Shem wrote:

    https://docs.racket-lang.org/reference/sync.html

    I had a look at that. Why do languages feel they have to stack on thick >>layers of extra abstraction on top of basic POSIX concepts?

    For one thing, because Windows is not POSIX compliant.

    Microsoft lawyers called me to say Microsoft supports ISO-IEC
    9945-1:1990 --- and, having installed Cygwin, they could not distinguish
    a POSIX compliant system from Microsoft Windows. I said our team would
    get back to them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to George Neuner on Fri Dec 29 20:53:25 2023
    On Fri, 29 Dec 2023 10:54:14 -0500, George Neuner wrote:

    On Fri, 29 Dec 2023 06:04:52 -0000 (UTC), Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    So you have to ask yourself: is your return from supporting Windows
    users worth the greatly increased expense?

    More people directly use Windows than directly use Unix/Linux.

    If you are publishing an open-source project, then it’s not the number of users that matters, but the level of contributions you get back from an
    active community.

    Bringing out a Windows build will almost certainly lead to a massive
    increase in your user base and in numbers of bug reports and complaints
    and general noise, without a concomitant increase in the level of
    contributions back from those Windows users. Comparatively very few
    Windows users have any idea about software development (or how to write
    good bug reports), and the platform itself is inherently not very friendly
    to open-source development.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From George Neuner@21:1/5 to All on Sun Dec 31 01:31:34 2023
    On Fri, 29 Dec 2023 13:52:41 -0300, Julieta Shem <jshem@yaxenu.org>
    wrote:

    George Neuner <gneuner2@comcast.net> writes:

    On Fri, 29 Dec 2023 02:19:44 -0000 (UTC), Lawrence D'Oliveiro
    <ldo@nz.invalid> wrote:

    On Tue, 26 Dec 2023 12:25:11 -0300, Julieta Shem wrote:

    https://docs.racket-lang.org/reference/sync.html

    I had a look at that. Why do languages feel they have to stack on thick >>>layers of extra abstraction on top of basic POSIX concepts?

    For one thing, because Windows is not POSIX compliant.

    Microsoft lawyers called me to say Microsoft supports ISO-IEC
    9945-1:1990 --- and, having installed Cygwin, they could not distinguish
    a POSIX compliant system from Microsoft Windows. I said our team would
    get back to them.

    The key part there is "after installing cygwin".

    The Windows APIs are not POSIX, but for the most part they provide
    equivalent functionality, so POSIX calls can be translated into
    Windows call (with varying degrees of difficulty, the asynch stuff in particular is completely different). This is what cygwin does.

    cygwin, however, has its own problems ... it is known to be unstable.


    Moreover, Windows supports only a handful of signals, so if you want
    to use one it doesn't support, your're out of luck. https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/signal?view=msvc-170
    https://www.man7.org/linux/man-pages/man7/signal.7.html

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to George Neuner on Sun Dec 31 07:08:15 2023
    On Sun, 31 Dec 2023 01:31:34 -0500, George Neuner wrote:

    The Windows APIs are not POSIX, but for the most part they provide
    equivalent functionality, so POSIX calls can be translated into Windows
    call (with varying degrees of difficulty, the asynch stuff in particular
    is completely different). This is what cygwin does.

    Actually, Cygwin actually manages to do something a bit better than that.

    Consider the select/poll calls
    <https://docs.python.org/3/library/select.html>: note the caveat that, on Windows, they only work on sockets, whereas on regular POSIX OSes they
    work on other things, in particular pipes.

    Cygwin manages to implement its select/poll calls on pipes, on Windows.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Lawrence D'Oliveiro on Sun Dec 31 07:27:56 2023
    On 2023-12-31, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Sun, 31 Dec 2023 01:31:34 -0500, George Neuner wrote:

    The Windows APIs are not POSIX, but for the most part they provide
    equivalent functionality, so POSIX calls can be translated into Windows
    call (with varying degrees of difficulty, the asynch stuff in particular
    is completely different). This is what cygwin does.

    Actually, Cygwin actually manages to do something a bit better than that.

    Consider the select/poll calls
    <https://docs.python.org/3/library/select.html>: note the caveat that, on
    Windows, they only work on sockets, whereas on regular POSIX OSes they
    work on other things, in particular pipes.

    Cygwin manages to implement its select/poll calls on pipes, on Windows.

    In 2016 I started a small project called Cygnal which turns the Cygwin
    DLL into a "Native Windows" run-time library.

    Since then, I've been using that as the basis of the Windows port of
    the TXR language: that version that uses the executable installer.

    You can compile a program under Cygwin, as a Cygwin program. Then
    bundle it with the CYGWIN1.DLL from Cygnal, and ship it as a Cygnal
    program.

    As a Cygnal program, it enjoys a number of native-like conventions:

    - native paths like C:\Users\bob\file.txt (no /cygdrive stuff).
    - the otherwise POSIX chdir() function implements the DOS/Windows
    "logged drive" concept.
    - PATH is semicolon separated, once again.

    - ... other things, all documented:

    http://kylheku.com/cygnal

    Cygnal is probably the best way to port a POSIX program to Windows.

    (If there were a better way, I'd have used that instead of bothering
    with making a Cygwin DLL fork.)

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Kaz Kylheku on Sun Dec 31 08:37:25 2023
    On Sun, 31 Dec 2023 07:27:56 -0000 (UTC), Kaz Kylheku wrote:

    Cygnal is probably the best way to port a POSIX program to Windows.

    There is a better way now, and that is WSL2.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Lawrence D'Oliveiro on Sun Dec 31 17:20:16 2023
    On 2023-12-31, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Sun, 31 Dec 2023 07:27:56 -0000 (UTC), Kaz Kylheku wrote:

    Cygnal is probably the best way to port a POSIX program to Windows.

    There is a better way now, and that is WSL2.

    I don't think so. With Cygnal, you deliver an .exe accompanied by
    a DLL or two, and that's it.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Kaz Kylheku on Sun Dec 31 21:20:47 2023
    On Sun, 31 Dec 2023 17:20:16 -0000 (UTC), Kaz Kylheku wrote:

    On 2023-12-31, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    On Sun, 31 Dec 2023 07:27:56 -0000 (UTC), Kaz Kylheku wrote:

    Cygnal is probably the best way to port a POSIX program to Windows.

    There is a better way now, and that is WSL2.

    I don't think so. With Cygnal, you deliver an .exe accompanied by a DLL
    or two, and that's it.

    WSL2 at least lets you run a proper Linux distro, with proper package management.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From De ongekruisigde@21:1/5 to Lawrence D'Oliveiro on Sun Dec 31 21:30:18 2023
    On 2023-12-31, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Sun, 31 Dec 2023 17:20:16 -0000 (UTC), Kaz Kylheku wrote:

    On 2023-12-31, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    On Sun, 31 Dec 2023 07:27:56 -0000 (UTC), Kaz Kylheku wrote:

    Cygnal is probably the best way to port a POSIX program to Windows.

    There is a better way now, and that is WSL2.

    I don't think so. With Cygnal, you deliver an .exe accompanied by a DLL
    or two, and that's it.

    WSL2 at least lets you run a proper Linux distro, with proper package management.

    Frickin Windows as a host for Linux? That's a recipe for disaster
    (MS Windows must die; thank you).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to De ongekruisigde on Sun Dec 31 23:49:18 2023
    On Sun, 31 Dec 2023 21:30:18 -0000 (UTC), De ongekruisigde wrote:

    Frickin Windows as a host for Linux? That's a recipe for disaster (MS
    Windows must die; thank you).

    Microsoft has no choice: it has to do something to stem the tide of
    developers deserting Windows for Linux. Of course WSL2 is a kludge. But
    then the whole history of Windows is of piling kludges on kludges, for short-term profit-driven reasons.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Lawrence D'Oliveiro on Sun Dec 31 21:48:06 2023
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sun, 31 Dec 2023 17:20:16 -0000 (UTC), Kaz Kylheku wrote:

    On 2023-12-31, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    On Sun, 31 Dec 2023 07:27:56 -0000 (UTC), Kaz Kylheku wrote:

    Cygnal is probably the best way to port a POSIX program to Windows.

    There is a better way now, and that is WSL2.

    I don't think so. With Cygnal, you deliver an .exe accompanied by a DLL
    or two, and that's it.

    WSL2 at least lets you run a proper Linux distro, with proper package management.

    Funny you say proper package management as if UNIX ever had this ---
    before GNU Guix.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Lawrence D'Oliveiro on Sun Dec 31 21:47:16 2023
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sun, 31 Dec 2023 21:30:18 -0000 (UTC), De ongekruisigde wrote:

    Frickin Windows as a host for Linux? That's a recipe for disaster (MS
    Windows must die; thank you).

    Microsoft has no choice: it has to do something to stem the tide of developers deserting Windows for Linux. Of course WSL2 is a kludge. But
    then the whole history of Windows is of piling kludges on kludges, for short-term profit-driven reasons.

    It's pretty useful.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Julieta Shem on Mon Jan 1 02:37:07 2024
    On Sun, 31 Dec 2023 21:48:06 -0300, Julieta Shem wrote:

    Funny you say proper package management as if UNIX ever had this ---
    before GNU Guix.

    Where was there a “Unix” that had this? It was pretty much developed and refined by Debian and Red Hat, from about 1993 onwards.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Lawrence D'Oliveiro on Mon Jan 1 00:02:57 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sun, 31 Dec 2023 21:48:06 -0300, Julieta Shem wrote:

    Funny you say proper package management as if UNIX ever had this ---
    before GNU Guix.

    Where was there a “Unix” that had this? It was pretty much developed and refined by Debian and Red Hat, from about 1993 onwards.

    Funny you think that Debian and Red Hat ever had it. What they seem to
    have done --- with all due respect --- is to compress files with
    metadata. Pretty useful, but I think that /management/ should be
    applied to GNU Guix, with due credit to Nix, the pioneer.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Julieta Shem on Mon Jan 1 03:07:10 2024
    On Mon, 01 Jan 2024 00:02:57 -0300, Julieta Shem wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sun, 31 Dec 2023 21:48:06 -0300, Julieta Shem wrote:

    Funny you say proper package management as if UNIX ever had this ---
    before GNU Guix.

    Where was there a “Unix” that had this? It was pretty much developed
    and refined by Debian and Red Hat, from about 1993 onwards.

    Funny you think that Debian and Red Hat ever had it. What they seem to
    have done --- with all due respect --- is to compress files with
    metadata.

    They do dependency management, which is a crucial capability. It allows
    for code reuse, sharing one copy of a dependency among multiple client packages, and one-stop upgradeability for everything installed.

    No offence if you didn’t understand that. Seems most Windows users have difficulty appreciating it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Lawrence D'Oliveiro on Mon Jan 1 03:20:05 2024
    On 2023-12-31, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Sun, 31 Dec 2023 17:20:16 -0000 (UTC), Kaz Kylheku wrote:

    On 2023-12-31, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    On Sun, 31 Dec 2023 07:27:56 -0000 (UTC), Kaz Kylheku wrote:

    Cygnal is probably the best way to port a POSIX program to Windows.

    There is a better way now, and that is WSL2.

    I don't think so. With Cygnal, you deliver an .exe accompanied by a DLL
    or two, and that's it.

    WSL2 at least lets you run a proper Linux distro, with proper package management.

    That's nice, but not what you want when you want to ship a Windows
    application: .exe plus a few .dll files, which run as ordinary Windows applications without a special additional environment.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Kaz Kylheku on Mon Jan 1 04:46:31 2024
    On Mon, 1 Jan 2024 03:20:05 -0000 (UTC), Kaz Kylheku wrote:

    On 2023-12-31, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    WSL2 at least lets you run a proper Linux distro, with proper package
    management.

    That's nice, but not what you want when you want to ship a Windows application ...

    Which is why WSL2 is likely to become a mandatory part of future Windows installs. I’m not saying that was Microsoft’s conscious plan in
    introducing it; but it is simply going to be the path of least resistance
    going forward.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Lawrence D'Oliveiro on Mon Jan 1 08:07:50 2024
    On 2024-01-01, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Mon, 1 Jan 2024 03:20:05 -0000 (UTC), Kaz Kylheku wrote:

    On 2023-12-31, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    WSL2 at least lets you run a proper Linux distro, with proper package
    management.

    That's nice, but not what you want when you want to ship a Windows
    application ...

    Which is why WSL2 is likely to become a mandatory part of future Windows installs.

    Might work in the future, and definitely won't work on older Windows,
    like 7.

    How easily do WSL2 programs work with the native Windows environment?

    Suppose that the current directory on the F: drive is \data,
    and the WSL2 program is given the path F:file.txt. Will it understand
    that the path means F:\data\file.txt?

    The Cygnal program will do that.

    WSL's FAQ says this:

    You can also access your local machine’s file system from within the
    Linux Bash shell – you’ll find your local drives mounted under the
    /mnt folder. For example, your C: drive is mounted under /mnt/c:

    That's not native; it's like /cygdrive/c in Cygwin. I fixed that;
    I got rid of /cygdrive/c and most of the path munging.

    WSL2 does not look like a way, in any shape or form, of porting a
    POSIX program to be a *native* Windows application.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Kaz Kylheku on Mon Jan 1 09:20:38 2024
    On 2024-01-01, Kaz Kylheku <433-929-6894@kylheku.com> wrote:
    On 2024-01-01, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Mon, 1 Jan 2024 03:20:05 -0000 (UTC), Kaz Kylheku wrote:

    On 2023-12-31, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    WSL2 at least lets you run a proper Linux distro, with proper package
    management.

    That's nice, but not what you want when you want to ship a Windows
    application ...

    Which is why WSL2 is likely to become a mandatory part of future Windows
    installs.

    Might work in the future, and definitely won't work on older Windows,
    like 7.

    How easily do WSL2 programs work with the native Windows environment?

    Suppose that the current directory on the F: drive is \data,
    and the WSL2 program is given the path F:file.txt. Will it understand
    that the path means F:\data\file.txt?

    The Cygnal program will do that.

    WSL's FAQ says this:

    You can also access your local machine’s file system from within the
    Linux Bash shell – you’ll find your local drives mounted under the
    /mnt folder. For example, your C: drive is mounted under /mnt/c:

    That's not native; it's like /cygdrive/c in Cygwin. I fixed that;
    I got rid of /cygdrive/c and most of the path munging.

    In a Cygnal program you can use Win32 APIs. Can you use Win32 APIs
    in a WSL2 program?

    In the same C program, you can do this

    #include <termios.h>

    and use tcgetattr/tcsetattr to fiddle with TTY settings that
    really work with Windows consoles, and you can do this:

    #include <windows.h>

    and use MessageBox, CreateWindow and whatnot.

    Your mostly POSIX program can have some Windows-specific personality
    bits to it.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Kaz Kylheku on Mon Jan 1 21:34:27 2024
    On Mon, 1 Jan 2024 08:07:50 -0000 (UTC), Kaz Kylheku wrote:

    On 2024-01-01, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    Which is why WSL2 is likely to become a mandatory part of future
    Windows installs.

    Might work in the future, and definitely won't work on older Windows,
    like 7.

    Which nobody uses any more--nobody that Microsoft cares about, anyway.

    How easily do WSL2 programs work with the native Windows environment?

    They don’t need to, won’t need to.

    Windows programs, on the other hand, will be working, unbeknownst to them, through an emulation layer not entirely unlike WINE, onto the Linux
    kernel.

    Suppose that the current directory on the F: drive is \data,
    and the WSL2 program is given the path F:file.txt. Will it understand
    that the path means F:\data\file.txt?

    No, it means what you said, which is “F:file.txt”. Just tried this:

    ldo@theon:~> touch F:file.txt
    ldo@theon:~> ls -l F:file.txt
    -rw-r--r-- 1 ldo users 0 Jan 2 10:32 F:file.txt

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Kaz Kylheku on Mon Jan 1 23:08:02 2024
    On Mon, 1 Jan 2024 22:51:59 -0000 (UTC), Kaz Kylheku wrote:

    On 2024-01-01, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    On Mon, 1 Jan 2024 08:07:50 -0000 (UTC), Kaz Kylheku wrote:

    How easily do WSL2 programs work with the native Windows environment?

    They don’t need to, won’t need to.

    It's nice that you can drop that requirement. I have that requirement.

    You have the requirement to run Windows software, you only care that it
    works, not that it is running on a “true” Windows kernel rather than on Linux via emulation.

    Suppose that the current directory on the F: drive is \data,
    and the WSL2 program is given the path F:file.txt. Will it understand
    that the path means F:\data\file.txt?

    No, it means what you said, which is “F:file.txt”. Just tried this:

    ldo@theon:~> touch F:file.txt
    ldo@theon:~> ls -l F:file.txt
    -rw-r--r-- 1 ldo users 0 Jan 2 10:32 F:file.txt

    Well, that is not native Windows behavior ...

    Of course not. It’s Linux behaviour. That’s how programs running under Linux expect things to work. Or at least native Linux behaviour: I’m sure
    an emulation layer like WINE can make things look more Windows-like, if
    you want. But then, it will no longer be a “WSL2 program”, will it? It
    will just be a “Windows program”.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Lawrence D'Oliveiro on Mon Jan 1 22:51:59 2024
    On 2024-01-01, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Mon, 1 Jan 2024 08:07:50 -0000 (UTC), Kaz Kylheku wrote:

    On 2024-01-01, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    Which is why WSL2 is likely to become a mandatory part of future
    Windows installs.

    Might work in the future, and definitely won't work on older Windows,
    like 7.

    Which nobody uses any more--nobody that Microsoft cares about, anyway.

    How easily do WSL2 programs work with the native Windows environment?

    They don’t need to, won’t need to.

    It's nice that you can drop that requirement. I have that requirement.

    I use the Cygnal run-time to support a programming language in the Lisp
    family, and that programming language has access to a POSIX view of the
    world, but also supports Windows programming via FFI.

    This is achieved via simple mechanism: a run-time support C library DLL
    that has the POSIX stuff earnestly implemented on top of Win32.

    (It's analogous to Visual Studio's redistributable run-time library
    or the newer Universal CRT. Those do not have POSIX support in them,
    (or not any that is worth a damn) and also don't have a Unix-like build environment that supports a configure shell script and all that.)

    Windows programs, on the other hand, will be working, unbeknownst to them, through an emulation layer not entirely unlike WINE, onto the Linux
    kernel.

    That's just building conjectures upon guesses.

    Suppose that the current directory on the F: drive is \data,
    and the WSL2 program is given the path F:file.txt. Will it understand
    that the path means F:\data\file.txt?

    No, it means what you said, which is “F:file.txt”. Just tried this:

    ldo@theon:~> touch F:file.txt
    ldo@theon:~> ls -l F:file.txt
    -rw-r--r-- 1 ldo users 0 Jan 2 10:32 F:file.txt

    Well, that is not native Windows behavior, is it! In Windows, F: is a
    drive letter name. If it's not followed by a slash or backslash, the
    rest of it is a relative path resolved relative to the current working directory for that drive. Each drive has its own current working
    directory! There is also a current drive, the "currently logged drive".





    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Julieta Shem on Thu Jan 4 23:04:49 2024
    Julieta Shem <jshem@yaxenu.org> writes:

    [...]

    In C I would have used select. But how do I select in Racket? I found Racket's sync/timeout, a procedure based on Racket's ``events''. The reference dissertates briefly about events at

    https://docs.racket-lang.org/reference/sync.html

    and they cite

    John H. Reppy, Concurrent Programming in ML, Cambridge University
    Press, 1999. https://doi.org/10.1017/CBO9780511574962

    as a reference. It's unclear to me that this is what I'm looking for,
    but it might very well be.

    #lang racket/base
    (define (read-line-timeout [timeout 60] [port (current-input-port)])
    (define port-or-false
    (sync/timeout timeout port))
    (and port-or-false (read-line port-or-false)))

    (define (interact-with-timeout timeout)
    (define ln (read-line-timeout timeout))
    (cond [(not ln)
    (say "> God, you're slow.")]
    [(eof-object? ln)
    (say "> Okay, see you later.")]
    [else
    (say (format "< ~a" ln))
    (say "> But why do you say that?")
    (interact-with-timeout timeout)]))

    (define (say s) (displayln s) (flush-output))

    (module+ main
    (say "> Hello. Say anything and press RET.")
    (interact-with-timeout 3))

    As an exercise for in CL, I tried to write such procedure in CL using
    select(2) or poll(2). I failed: did not find documentation to use the
    SB-UNIX package. I see all procedures I want are there, but I have no instruction as how to use data construtors to prepare arguments for a
    procedure such as UNIX-FAST-SELECT. I found

    https://koji-kojiro.github.io/sb-docs/build/html/index.html

    which seems helpful, but with no examples. Given that I could write
    such program in C using select(2) or poll(2), would there be anything
    you could say here that would give me a direction? Thank you! Any
    interesting publication that I so far failed to have found? (For
    instance, I have Peter Seibel's Practical Common Lisp, but it doesn't
    seem to help me with this exercise.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Julieta Shem on Fri Jan 5 02:55:05 2024
    On 2024-01-05, Julieta Shem <jshem@yaxenu.org> wrote:
    which seems helpful, but with no examples. Given that I could write
    such program in C using select(2) or poll(2), would there be anything
    you could say here that would give me a direction? Thank you! Any interesting publication that I so far failed to have found? (For
    instance, I have Peter Seibel's Practical Common Lisp, but it doesn't
    seem to help me with this exercise.)

    One thing to watch out for, in any language, is if you're reading
    from high level buffered streams but trying to use select or poll.
    (This goes for C stdio also.)

    You don't want to be accidentally blocking in select or poll
    while the stream contains unread, buffered data (already transferred
    from the operating system descriptor to user space).

    That can happen if the stream reads more data than your program
    requested. E.g. you're looking for one byte, and poll. The stream
    initially has nothing so this is right. Poll unblocks when data
    becomes available, so you read the one byte from the stream. But suppose
    that the stream actually reads 500 bytes from the OS, giving you 1 and buffering 499. After that, you have to read the available 499 bytes
    from the stream before calling poll (unless poll is aware of streams,
    rather than just a thin wrapper for the POSIX function.)

    You have to put the underlying descriptor into non-blocking mode
    (even if you're only reading from that one). Then whenever it polls
    positive, read all available data from the stream until it hits an
    error from the file descriptor with EWOULDBLOCK.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Kaz Kylheku on Fri Jan 5 01:19:21 2024
    Kaz Kylheku <433-929-6894@kylheku.com> writes:

    On 2024-01-05, Julieta Shem <jshem@yaxenu.org> wrote:
    which seems helpful, but with no examples. Given that I could write
    such program in C using select(2) or poll(2), would there be anything
    you could say here that would give me a direction? Thank you! Any
    interesting publication that I so far failed to have found? (For
    instance, I have Peter Seibel's Practical Common Lisp, but it doesn't
    seem to help me with this exercise.)

    One thing to watch out for, in any language, is if you're reading
    from high level buffered streams but trying to use select or poll.
    (This goes for C stdio also.)

    You don't want to be accidentally blocking in select or poll
    while the stream contains unread, buffered data (already transferred
    from the operating system descriptor to user space).

    That can happen if the stream reads more data than your program
    requested. E.g. you're looking for one byte, and poll. The stream
    initially has nothing so this is right. Poll unblocks when data
    becomes available, so you read the one byte from the stream. But suppose
    that the stream actually reads 500 bytes from the OS, giving you 1 and buffering 499. After that, you have to read the available 499 bytes
    from the stream before calling poll (unless poll is aware of streams,
    rather than just a thin wrapper for the POSIX function.)

    You have to put the underlying descriptor into non-blocking mode
    (even if you're only reading from that one). Then whenever it polls
    positive, read all available data from the stream until it hits an
    error from the file descriptor with EWOULDBLOCK.

    I need to learn to put file descriptors in non-blocking mode. Thanks
    for reminding me. Surely an abstraction to handle this is desired. The problem seems to boil down to reading a partial line in the buffer
    without having the rest of it --- say coming from the network still.
    The procedure for reading such lines should somehow hold the partial
    line until it completes.

    I managed to discover UNIX-SIMPLE-POLL in SB-UNIX. Here's a procedure
    that suffers from the problem you warned me above.

    --8<---------------cut here---------------start------------->8---
    (defun read-line-timeout (s)
    "reads a line from stdin or times out in S seconds."
    (let ((ready (sb-unix:unix-simple-poll 0 :input (* 1000 s))))
    (cond (ready (format t "I read: ~a~%" (read-line)))
    (t (format t "God, you're slow.~%")))))

    ;; main =
    (read-line-timeout 3)
    --8<---------------cut here---------------end--------------->8---

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Madhu@21:1/5 to All on Fri Jan 5 17:34:20 2024
    * Julieta Shem <87frzcwgxi.fsf @yaxenu.org> :
    Wrote on Fri, 05 Jan 2024 01:19:21 -0300:
    I need to learn to put file descriptors in non-blocking mode. Thanks
    for reminding me. Surely an abstraction to handle this is desired. The problem seems to boil down to reading a partial line in the buffer
    without having the rest of it --- say coming from the network still.
    The procedure for reading such lines should somehow hold the partial
    line until it completes.

    I managed to discover UNIX-SIMPLE-POLL in SB-UNIX. Here's a procedure
    that suffers from the problem you warned me above.

    (defun read-line-timeout (s)
    "reads a line from stdin or times out in S seconds."
    (let ((ready (sb-unix:unix-simple-poll 0 :input (* 1000 s))))
    (cond (ready (format t "I read: ~a~%" (read-line)))
    (t (format t "God, you're slow.~%")))))

    ;; main =
    (read-line-timeout 3)

    I think a better way to approach this is to (somehow) set a
    stream-timout on the stream and have read-line (on your special stream)
    return nil (or a supplied on-timeout value) if there is no data on the
    stream. your lisp code in your thread would still deal with a blocking
    read.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Madhu on Fri Jan 5 14:32:14 2024
    Madhu <enometh@meer.net> writes:

    * Julieta Shem <87frzcwgxi.fsf @yaxenu.org> :
    Wrote on Fri, 05 Jan 2024 01:19:21 -0300:
    I need to learn to put file descriptors in non-blocking mode. Thanks
    for reminding me. Surely an abstraction to handle this is desired. The
    problem seems to boil down to reading a partial line in the buffer
    without having the rest of it --- say coming from the network still.
    The procedure for reading such lines should somehow hold the partial
    line until it completes.

    I managed to discover UNIX-SIMPLE-POLL in SB-UNIX. Here's a procedure
    that suffers from the problem you warned me above.

    (defun read-line-timeout (s)
    "reads a line from stdin or times out in S seconds."
    (let ((ready (sb-unix:unix-simple-poll 0 :input (* 1000 s))))
    (cond (ready (format t "I read: ~a~%" (read-line)))
    (t (format t "God, you're slow.~%")))))

    ;; main =
    (read-line-timeout 3)

    I think a better way to approach this is to (somehow) set a
    stream-timout on the stream and have read-line (on your special stream) return nil (or a supplied on-timeout value) if there is no data on the stream. your lisp code in your thread would still deal with a blocking
    read.

    Sounds interesting. It's a stream like stdin, stdout, stderr, but it
    has a timeout associate with it. Reading or writing to it times out if
    nothing usual happens before. Is that the idea?

    It's a bit scary that this isn't done by any library given all the years
    of SBCL. What's up with that? I'm not talking about CL as a standard
    --- I'm talking about the implementations. In practice we need all of
    these system-specific things.

    I was expecting replies in the form --- hold it, young Skywalker: here's
    how we've doing this for decades. I'm a total beginner. The procedure
    above is my first procedure in CL. It makes me feel that the most
    useful thing I can do in CL is learn about the SBCL's FFI. That's no complaint. I'm just trying to understand the Lisp world.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Madhu on Fri Jan 5 21:57:38 2024
    On Fri, 05 Jan 2024 17:34:20 +0530, Madhu wrote:

    I think a better way to approach this is to (somehow) set a
    stream-timout on the stream and have read-line (on your special stream) return nil (or a supplied on-timeout value) if there is no data on the stream. your lisp code in your thread would still deal with a blocking
    read.

    Remember the main point of select/poll, in that it lets you non- deterministically wait on a number of file descriptors at once, and
    respond immediately to the first one that has any I/O to do.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Lawrence D'Oliveiro on Fri Jan 5 20:57:43 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Fri, 05 Jan 2024 17:34:20 +0530, Madhu wrote:

    I think a better way to approach this is to (somehow) set a
    stream-timout on the stream and have read-line (on your special stream)
    return nil (or a supplied on-timeout value) if there is no data on the
    stream. your lisp code in your thread would still deal with a blocking
    read.

    Remember the main point of select/poll, in that it lets you non- deterministically wait on a number of file descriptors at once, and
    respond immediately to the first one that has any I/O to do.

    I think Madhu's mind is on handling just a single file descriptor but
    with a timeout (and with all the conform of a stream).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Julieta Shem on Fri Jan 5 21:15:12 2024
    Julieta Shem <jshem@yaxenu.org> writes:

    Kaz Kylheku <433-929-6894@kylheku.com> writes:

    On 2024-01-05, Julieta Shem <jshem@yaxenu.org> wrote:
    which seems helpful, but with no examples. Given that I could write
    such program in C using select(2) or poll(2), would there be anything
    you could say here that would give me a direction? Thank you! Any
    interesting publication that I so far failed to have found? (For
    instance, I have Peter Seibel's Practical Common Lisp, but it doesn't
    seem to help me with this exercise.)

    One thing to watch out for, in any language, is if you're reading
    from high level buffered streams but trying to use select or poll.
    (This goes for C stdio also.)

    You don't want to be accidentally blocking in select or poll
    while the stream contains unread, buffered data (already transferred
    from the operating system descriptor to user space).

    That can happen if the stream reads more data than your program
    requested. E.g. you're looking for one byte, and poll. The stream
    initially has nothing so this is right. Poll unblocks when data
    becomes available, so you read the one byte from the stream. But suppose
    that the stream actually reads 500 bytes from the OS, giving you 1 and
    buffering 499. After that, you have to read the available 499 bytes
    from the stream before calling poll (unless poll is aware of streams,
    rather than just a thin wrapper for the POSIX function.)

    You have to put the underlying descriptor into non-blocking mode
    (even if you're only reading from that one). Then whenever it polls
    positive, read all available data from the stream until it hits an
    error from the file descriptor with EWOULDBLOCK.

    I need to learn to put file descriptors in non-blocking mode. Thanks
    for reminding me.

    It turns out SB-POSIX provides fcntl().

    --8<---------------cut here---------------start------------->8---
    (require 'sb-posix)
    (defun ndelay-on (fd)
    (sb-posix:fcntl fd
    sb-posix:f-setfl
    (logior sb-posix:o-nonblock
    (sb-posix:fcntl fd sb-posix:f-getfl 0)))) --8<---------------cut here---------------end--------------->8---

    Reading the source of SB-UNIX, I managed to learn how to invoke
    UNIX-READ. So I was able to write the following procedure. It puts the
    FD into non-blocking mode, then it allocates a buffer using SB-ALIEN,
    whose memory I have no idea who is freeing. I had to learn how to close
    the c-string. Small buffer of size 10 on purpose.

    --8<---------------cut here---------------start------------->8---
    (defun ndelay-read-from-fd (fd)
    (ndelay-on fd)
    (let ((buf (make-alien (array char 10))))
    (multiple-value-bind (nbytes-or-nil errno)
    ;; spare a byte for closing the c-string
    (sb-unix:unix-read fd (alien-sap buf) (1- 10))
    (cond ((null nbytes-or-nil) (values nil errno))
    (t
    ;; close the c-string
    (setf (deref (deref buf 0) nbytes-or-nil) 0)
    (values nbytes-or-nil buf))))))
    --8<---------------cut here---------------end--------------->8---

    As a sample program, I wrote ndelay-read-line. The ``read-line'' is
    surely illusory because I'm not parsing lines at all. Maybe Madhu is
    going to wrap this code with a stream ``somehow''. :-)

    --8<---------------cut here---------------start------------->8---
    (defun ndelay-read-line ()
    (defun strerror (n) (if (= n 11) "EGAIN" "EDONTKNOW"))
    (multiple-value-bind (nbytes-or-nil alien-or-errno) (ndelay-read-from-fd 0)
    (cond ((and (null nbytes-or-nil))
    (format t "errno = ~a~%" (strerror alien-or-errno)))
    ((= 0 nbytes-or-nil)
    (format t "eof (read returned 0 bytes)~%"))
    (t (format t "~a..."
    (cast alien-or-errno c-string))
    (ndelay-read-line)))))

    ;; main =
    (ndelay-read-line)
    --8<---------------cut here---------------end--------------->8---

    We can call this a second exercise. I suppose I have enough for the
    third exercise of polling the FD with a timeout and be sure we will not
    block if the data is not a full line. It will surely take more
    abstraction. (Eventually I need to learn what is being allocated and
    who is to free it and when.)

    Someone pointed me out to CFFI at

    https://cffi.common-lisp.dev/

    with the promise of being more expressive than SB-ALIEN.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Madhu@21:1/5 to All on Sat Jan 6 21:52:48 2024
    * Julieta Shem <87jzonvg81.fsf @yaxenu.org> :
    Wrote on Fri, 05 Jan 2024 14:32:14 -0300:

    Madhu <enometh@meer.net> writes:
    I think a better way to approach this is to (somehow) set a
    stream-timout on the stream and have read-line (on your special stream)
    return nil (or a supplied on-timeout value) if there is no data on the
    stream. your lisp code in your thread would still deal with a blocking
    read.

    Sounds interesting. It's a stream like stdin, stdout, stderr, but it
    has a timeout associate with it. Reading or writing to it times out if nothing usual happens before. Is that the idea?

    It's a bit scary that this isn't done by any library given all the years
    of SBCL. What's up with that? I'm not talking about CL as a standard
    --- I'm talking about the implementations. In practice we need all of
    these system-specific things.

    I was expecting replies in the form --- hold it, young Skywalker: here's
    how we've doing this for decades. I'm a total beginner. The procedure
    above is my first procedure in CL. It makes me feel that the most
    useful thing I can do in CL is learn about the SBCL's FFI. That's no complaint. I'm just trying to understand the Lisp world.

    I searched for a published example but I didn't find it -- I have an
    example in an implementation of a "https stream" a subclass of fd-stream (probably derived from something "emarsden" posted somewhere, but i
    can't find it) which specializes the fd-stream class and adds a
    connection timeout. IIRC This integrates with the SERVE-EVENT
    abstraction which is a co-ooperative multiprocessing layer about select,
    and the implementation is tied to SERVE-EVENT, if the fd is not usable
    (data does not arrive on it in the given time), it raises a timeout
    error.

    On second thoughts I don't think it will solve your problem. I just
    thought this was the way to approach the problem: call READ and handle a timeout condition (from the implementation)

    I think the CMUCL code base still has the code for a netnews client for hemlock, though it doesn't use this strategy. You can see the code from
    1980, (which has not yet been deleted by some open source who has been
    hired to delete it) here https://gitlab.common-lisp.net/cmucl/cmucl/-/blob/master/src/hemlock/netnews.lisp
    (or wihout js) https://gitlab.common-lisp.net/cmucl/cmucl/-/raw/master/src/hemlock/netnews.lisp

    I checked trivial-nntp (probably in quicklisp) but it just wraps usocket
    and doesnt deal with timeouts. iolib also doesnt seem to expose any
    setsock SO_RCVTIMEO, though it can probably used, i havent figured it
    out, i'll have to look again later.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Axel Reichert@21:1/5 to Julieta Shem on Sat Jan 6 19:55:00 2024
    Julieta Shem <jshem@yaxenu.org> writes:

    Funny you think that Debian and Red Hat ever had it. What they seem to
    have done --- with all due respect --- is to compress files with
    metadata. Pretty useful, but I think that /management/ should be
    applied to GNU Guix, with due credit to Nix, the pioneer.

    If you are into GNU Guix (I am currently being tempted to switch), then
    you are aware of Guile (methinks you mentioned it in another thread),
    which brings me back to your original question: Since Guile is
    advertised with its POSIX capabilities, I expect you could find
    a better/more familiar technique there.

    But that is just guessing and gut feeling, not based on any research.

    Best regards

    Axel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Madhu on Sat Jan 6 18:43:24 2024
    Madhu <enometh@meer.net> writes:

    * Julieta Shem <87jzonvg81.fsf @yaxenu.org> :
    Wrote on Fri, 05 Jan 2024 14:32:14 -0300:

    Madhu <enometh@meer.net> writes:
    I think a better way to approach this is to (somehow) set a
    stream-timout on the stream and have read-line (on your special stream)
    return nil (or a supplied on-timeout value) if there is no data on the
    stream. your lisp code in your thread would still deal with a blocking
    read.

    Sounds interesting. It's a stream like stdin, stdout, stderr, but it
    has a timeout associate with it. Reading or writing to it times out if
    nothing usual happens before. Is that the idea?

    It's a bit scary that this isn't done by any library given all the years
    of SBCL. What's up with that? I'm not talking about CL as a standard
    --- I'm talking about the implementations. In practice we need all of
    these system-specific things.

    I was expecting replies in the form --- hold it, young Skywalker: here's
    how we've doing this for decades. I'm a total beginner. The procedure
    above is my first procedure in CL. It makes me feel that the most
    useful thing I can do in CL is learn about the SBCL's FFI. That's no
    complaint. I'm just trying to understand the Lisp world.

    I searched for a published example but I didn't find it -- I have an
    example in an implementation of a "https stream" a subclass of fd-stream (probably derived from something "emarsden" posted somewhere, but i
    can't find it) which specializes the fd-stream class and adds a
    connection timeout. IIRC This integrates with the SERVE-EVENT
    abstraction which is a co-ooperative multiprocessing layer about select,
    and the implementation is tied to SERVE-EVENT, if the fd is not usable
    (data does not arrive on it in the given time), it raises a timeout
    error.

    On second thoughts I don't think it will solve your problem.

    Let's talk about the problem, which I think we did not do too much yet.
    The exercise is not an NNTP client, but a server. I think the server
    should not be totally naive when it comes to waiting for peers to talk.
    (Even though I believe a denial-of-service might be a too-difficult
    problem to solve. I don't even know what ``perfect'' protection against
    such attacks would be.) I would imagine that TCP already solves the
    timeout problem, but still --- I feel like it should be an easy exercise
    for a program to handle that itself. So, my exercise was to read a file descriptor with a timeout --- give me your command or die.

    I just thought this was the way to approach the problem: call READ and
    handle a timeout condition (from the implementation)

    I think the CMUCL code base still has the code for a netnews client for hemlock, though it doesn't use this strategy. You can see the code from
    1980, (which has not yet been deleted by some open source who has been
    hired to delete it) here https://gitlab.common-lisp.net/cmucl/cmucl/-/blob/master/src/hemlock/netnews.lisp
    (or wihout js) https://gitlab.common-lisp.net/cmucl/cmucl/-/raw/master/src/hemlock/netnews.lisp

    Thanks. That's fun reading.

    I checked trivial-nntp (probably in quicklisp) but it just wraps
    usocket and doesnt deal with timeouts. iolib also doesnt seem to
    expose any setsock SO_RCVTIMEO, though it can probably used, i havent
    figured it out, i'll have to look again later.

    Thanks for looking into it.

    The strategy that I would apply to the exercise is to use a TCP server.
    I suppose usocket implies sockets but my exercise expects to handle just standard input, so I guess I could not really use a socket library for anything.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Axel Reichert on Sat Jan 6 18:32:26 2024
    Axel Reichert <mail@axel-reichert.de> writes:

    Julieta Shem <jshem@yaxenu.org> writes:

    Funny you think that Debian and Red Hat ever had it. What they seem to
    have done --- with all due respect --- is to compress files with
    metadata. Pretty useful, but I think that /management/ should be
    applied to GNU Guix, with due credit to Nix, the pioneer.

    If you are into GNU Guix (I am currently being tempted to switch), then
    you are aware of Guile (methinks you mentioned it in another thread),

    I did.

    which brings me back to your original question: Since Guile is
    advertised with its POSIX capabilities, I expect you could find a
    better/more familiar technique there.

    But that is just guessing and gut feeling, not based on any research.

    Relative to my desires that's good intuition. I've been looking for a
    Lisp as a medium of expression and Racket does appear to be the most sophisticated one. However, it's still too early for me to be really
    taken by any language --- it takes so many years. People here called my attention to Common Lisp and even though I've only effectively spent a
    few hours on it I'm impressed by how much fun it has been. Somehow
    Racket has not done this for me, despite a much more considerable
    investment I've already made into it --- relative to Common Lisp. But,
    as you hypothesized, seeing how much fun I was having just considering
    Common Lisp I did think of Guile precisely because of the GNU Guix
    connection. (I asked Kaz Kylheku what he thought of Guile, but I think
    he did not follow up or I did not see it somehow.)

    Right now --- the way I feel --- is kinda of a no-brainer: Common Lisp
    is fun. Why is it more fun than the all the beauty of Racket? I don't
    know. I could elaborate, but a beginner's perspective doesn't sound
    very fruitful really.

    I half-jokingly remarked to a friend yesterday that reading Common Lisp documentation I felt like a computing historian. The SBCL manual,
    section 9.9, gives an example of a C function in K&R-style C --- pasted
    below. (I was just messing around.) Nevertheless, I do enjoy the
    history of computing quite a lot and it does feel good to actually use
    tools older than the current ones that actually feels /quite/ superior
    --- whatever that means. Even if it were inferior, it would still be
    fun to use, but since it feels quite the opposite then it's surreally interesting. (I saw a quote by Rich Hickey yesterday saying something
    like --- patterns mean you've ran out of language --- or something like
    that. I thought it was quite spot on.)

    --8<---------------cut here---------------start------------->8---
    struct c_struct *c_function (i, s, r, a)
    int i;
    char *s;
    struct c_struct *r;
    int a[10];
    {
    int j;
    struct c_struct *r2;
    printf("i = %d\n", i);
    printf("s = %s\n", s);
    printf("r->x = %d\n", r->x);
    printf("r->s = %s\n", r->s);
    for (j = 0; j < 10; j++) printf("a[%d] = %d.\n", j, a[j]);
    r2 = (struct c_struct *) malloc (sizeof(struct c_struct));
    r2->x = i + 5;
    r2->s = "a C string";
    return(r2);
    };
    --8<---------------cut here---------------end--------------->8---

    Thanks for the Guile suggestion.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Julieta Shem on Sat Jan 6 23:35:39 2024
    On Sat, 06 Jan 2024 18:43:24 -0300, Julieta Shem wrote:

    So, my exercise was to read a file
    descriptor with a timeout --- give me your command or die.

    Typically you will have multiple concurrent client connections going on.
    So you want an event loop that monitors all connections. Each one will
    have a last-active timer. The poll(2) call will have a timeout that
    corresponds to the earliest of these timer expirations. So if you don’t
    get any activity in that time (or even if you do), you start disconnecting
    idle clients.

    I have a worked example of this, in Python using asyncio here <https://gitlab.com/ldo/chunk_protocol_example>.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Lawrence D'Oliveiro on Sat Jan 6 22:43:54 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sat, 06 Jan 2024 18:43:24 -0300, Julieta Shem wrote:

    So, my exercise was to read a file
    descriptor with a timeout --- give me your command or die.

    Typically you will have multiple concurrent client connections going on.
    So you want an event loop that monitors all connections. Each one will
    have a last-active timer. The poll(2) call will have a timeout that corresponds to the earliest of these timer expirations. So if you don’t
    get any activity in that time (or even if you do), you start disconnecting idle clients.

    The exercise is much easier than that --- it's an NNTP server, so the
    service doesn't need to handle clients in a centralized manner. The TCP
    server will spawn the nntpd, which will only handle a single client.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Madhu@21:1/5 to All on Sun Jan 7 08:01:48 2024
    * Julieta Shem <87ttnpsysl.fsf @yaxenu.org> :
    Wrote on Sat, 06 Jan 2024 22:43:54 -0300:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sat, 06 Jan 2024 18:43:24 -0300, Julieta Shem wrote:

    So, my exercise was to read a file
    descriptor with a timeout --- give me your command or die.

    Typically you will have multiple concurrent client connections going
    on. So you want an event loop that monitors all connections. Each
    one will have a last-active timer. The poll(2) call will have a
    timeout that corresponds to the earliest of these timer
    expirations. So if you don’t get any activity in that time (or even
    if you do), you start disconnecting idle clients.

    The exercise is much easier than that --- it's an NNTP server, so the
    service doesn't need to handle clients in a centralized manner. The
    TCP server will spawn the nntpd, which will only handle a single
    client.

    TCPD is a nice abstraction but in my mind there is a conflict, bringing
    in lisp, also brings an unbearable urge to manage the file descriptors
    from lisp in a long running stateful lisp process, Personally I never
    got over this particular dissonance ("If I use lisp I _have_ to take
    advantage of this feature long-running-process -- or bust"), and prefer
    short small executables programs for processes. [OTOH I remember cl-http
    on buggy linux in 1996 which would result in a number of TCP connections
    which were never cleaned up for 2 days]

    Likewise "If I use Lisp I _have_ to take advantage of the stream
    abstraction and all the goodies of its stream design". In lisp stdin
    (when it is also *terminal-io*) is special because it is an interactive
    stream. You can call PEEK on it to see if there is data to be read and
    and handle some aspects of interactivity primitively through that. CL
    defines INTERACTIVE-STREAM-P and extensions like gray streams purport to support it. but when you get stdin from a fdstream or TCPstream, it
    isn't really special.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Julieta Shem@21:1/5 to Madhu on Sun Jan 7 02:55:44 2024
    Madhu <enometh@meer.net> writes:

    * Julieta Shem <87ttnpsysl.fsf @yaxenu.org> :
    Wrote on Sat, 06 Jan 2024 22:43:54 -0300:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sat, 06 Jan 2024 18:43:24 -0300, Julieta Shem wrote:

    So, my exercise was to read a file
    descriptor with a timeout --- give me your command or die.

    Typically you will have multiple concurrent client connections going
    on. So you want an event loop that monitors all connections. Each
    one will have a last-active timer. The poll(2) call will have a
    timeout that corresponds to the earliest of these timer
    expirations. So if you don’t get any activity in that time (or even
    if you do), you start disconnecting idle clients.

    The exercise is much easier than that --- it's an NNTP server, so the
    service doesn't need to handle clients in a centralized manner. The
    TCP server will spawn the nntpd, which will only handle a single
    client.

    TCPD is a nice abstraction but in my mind there is a conflict, bringing
    in lisp, also brings an unbearable urge to manage the file descriptors
    from lisp in a long running stateful lisp process, Personally I never
    got over this particular dissonance ("If I use lisp I _have_ to take advantage of this feature long-running-process -- or bust"), and prefer
    short small executables programs for processes. [OTOH I remember cl-http
    on buggy linux in 1996 which would result in a number of TCP connections which were never cleaned up for 2 days]

    Likewise "If I use Lisp I _have_ to take advantage of the stream
    abstraction and all the goodies of its stream design". In lisp stdin
    (when it is also *terminal-io*) is special because it is an interactive stream. You can call PEEK on it to see if there is data to be read and
    and handle some aspects of interactivity primitively through that. CL
    defines INTERACTIVE-STREAM-P and extensions like gray streams purport to support it. but when you get stdin from a fdstream or TCPstream, it
    isn't really special.

    I don't understand. The program is being written to handle a TCP
    connection. Terminals are not going to be connected to it. How would
    you handle that?

    I am thankful I can write the program with my keyboard attached to it
    and then later naturally switch it all to a TCP connection. Isn't that
    great?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Madhu@21:1/5 to All on Sun Jan 7 12:40:25 2024
    * Julieta Shem <87edetd6vz.fsf @yaxenu.org> :
    Wrote on Sun, 07 Jan 2024 02:55:44 -0300:
    Madhu <enometh@meer.net> writes:
    TCPD is a nice abstraction but in my mind there is a conflict, bringing
    in lisp, also brings an unbearable urge to manage the file descriptors
    from lisp in a long running stateful lisp process, Personally I never
    [...]

    Likewise "If I use Lisp I _have_ to take advantage of the stream
    abstraction and all the goodies of its stream design". In lisp stdin
    (when it is also *terminal-io*) is special because it is an interactive
    stream. You can call PEEK on it to see if there is data to be read and
    and handle some aspects of interactivity primitively through that. CL
    defines INTERACTIVE-STREAM-P and extensions like gray streams purport to
    support it. but when you get stdin from a fdstream or TCPstream, it
    isn't really special.

    I don't understand. The program is being written to handle a TCP
    connection. Terminals are not going to be connected to it. How would
    you handle that?

    I wouldn't. I just meant that using lisp for a program that reads
    standard input and writes to standard output would not be able to use
    the (admittedly limited) interactive features of interactive-stream-p
    and peek, which were designed to handle interactivity.

    Once you have to set non-blocking on the FD you've already breached the abstraction barrier (that limits you dealing solely with stdin
    stdout). When you want to do timeouts on the input, that is a another
    breach. You're no longer programming within the niceties where you
    program just reads stdin and handles stdout and leave TCPD to handle all
    the network and timeout issues. So now there is a sort of square/round peg/hole.


    I am thankful I can write the program with my keyboard attached to it
    and then later naturally switch it all to a TCP connection. Isn't that great?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Axel Reichert@21:1/5 to Julieta Shem on Wed Jan 10 22:45:37 2024
    Julieta Shem <jshem@yaxenu.org> writes:

    Axel Reichert <mail@axel-reichert.de> writes:

    which brings me back to your original question: Since Guile is
    advertised with its POSIX capabilities, I expect you could find a
    better/more familiar technique there.

    But that is just guessing and gut feeling, not based on any research.

    Relative to my desires that's good intuition. I've been looking for a
    Lisp as a medium of expression and Racket does appear to be the most sophisticated one.

    Sounds familiar. Some years back I was torn between (Steel Bank) Common
    Lisp, Clojure and Racket. From an aesthetic/minimalistic point of view,
    I prefer Lisp-1s/Schemes, but SBCL is just an awesome interactive
    experience in Emacs with SLIME and really fast. Clojure feels more
    modern (but I am allergic against anything related to Java) and Racket
    powerful (but somehow not pragmatic). Common Lisp seems more down to
    earth, but also baroque (its age shows).

    seeing how much fun I was having just considering Common Lisp I did
    think of Guile precisely because of the GNU Guix connection.

    I somewhere read that Guile is the most Common-Lisp-like of the Scheme implementations (if you ask for it, I will try to dig up the link). From
    my above paragraph, you can imagine that this is intriguing for
    me. Especially having a reasonably fast general purpose language that purportedly integrates well with everything POSIX or C (I do not speak
    C), can be used to configure (I should rather say "determine") the setup
    of an operating system (Guix SD) and, with this OS, also for Emacs
    (since Guix SD has Guile Emacs, which otherwise is said to be quite an endeavour to build/install). I really like to reduce the number of tools
    in my box, provided they are powerful and I am willing to learn them
    deeply.

    reading Common Lisp documentation I felt like a computing historian.

    [...]

    I do enjoy the history of computing quite a lot and it does feel good
    to actually use tools older than the current ones that actually feels
    /quite/ superior

    Sure, and again, sounds familiar. Emacs is old, AWK is old, Unix is
    old. Many of the good tools are old, it is called

    https://en.wikipedia.org/wiki/Lindy_effect

    Learn them early, try to master them until late in your life. (This
    makes sense only for both powerful and versatile tools.)

    Best regards

    Axel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From George Neuner@21:1/5 to mail@axel-reichert.de on Wed Jan 10 17:57:13 2024
    On Wed, 10 Jan 2024 22:45:37 +0100, Axel Reichert
    <mail@axel-reichert.de> wrote:

    Julieta Shem <jshem@yaxenu.org> writes:

    Axel Reichert <mail@axel-reichert.de> writes:

    which brings me back to your original question: Since Guile is
    advertised with its POSIX capabilities, I expect you could find a
    better/more familiar technique there.

    But that is just guessing and gut feeling, not based on any research.

    Relative to my desires that's good intuition. I've been looking for a
    Lisp as a medium of expression and Racket does appear to be the most
    sophisticated one.

    Sounds familiar. Some years back I was torn between (Steel Bank) Common
    Lisp, Clojure and Racket. From an aesthetic/minimalistic point of view,
    I prefer Lisp-1s/Schemes, but SBCL is just an awesome interactive
    experience in Emacs with SLIME and really fast. Clojure feels more
    modern (but I am allergic against anything related to Java) and Racket >powerful (but somehow not pragmatic). Common Lisp seems more down to
    earth, but also baroque (its age shows).

    seeing how much fun I was having just considering Common Lisp I did
    think of Guile precisely because of the GNU Guix connection.

    I somewhere read that Guile is the most Common-Lisp-like of the Scheme >implementations (if you ask for it, I will try to dig up the link). From
    my above paragraph, you can imagine that this is intriguing for
    me. Especially having a reasonably fast general purpose language that >purportedly integrates well with everything POSIX or C (I do not speak
    C), can be used to configure (I should rather say "determine") the setup
    of an operating system (Guix SD) and, with this OS, also for Emacs
    (since Guix SD has Guile Emacs, which otherwise is said to be quite an >endeavour to build/install). I really like to reduce the number of tools
    in my box, provided they are powerful and I am willing to learn them
    deeply.

    reading Common Lisp documentation I felt like a computing historian.

    [...]

    I do enjoy the history of computing quite a lot and it does feel good
    to actually use tools older than the current ones that actually feels
    /quite/ superior

    Sure, and again, sounds familiar. Emacs is old, AWK is old, Unix is
    old. Many of the good tools are old, it is called

    https://en.wikipedia.org/wiki/Lindy_effect

    Learn them early, try to master them until late in your life. (This
    makes sense only for both powerful and versatile tools.)

    Best regards

    Axel

    Question is whether you want to write GUI programs. Then Armed Bear
    Common Lisp, Clojure or Racket have the edge ... Armed Bear and
    Clojure can use Java-based GUI builders and libraries, and Racket has
    its own builder and libraries.

    Admittedly I'm not current with Lisp state of the art, but I'm not
    aware of any Lisp that comes with its own GUI builder. Certainly you
    can use FFI and a widget library, or create a GUI using some other
    language and connect your Lisp program to it.

    YMMV,
    George

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)