* [PATCH 1/2] rdelim: Add new procedure `for-rdelim-in-port`.
@ 2024-12-16 15:21 Adam Faiz
2024-12-16 15:24 ` [PATCH 2/2] doc: Add documentation for `for-rdelim-in-port` and, related procedures Adam Faiz
2024-12-16 16:46 ` [PATCH 1/2] rdelim: Add new procedure `for-rdelim-in-port` Nala Ginrut
0 siblings, 2 replies; 7+ messages in thread
From: Adam Faiz @ 2024-12-16 15:21 UTC (permalink / raw)
To: guile-devel; +Cc: Ricardo Wurmus, Tomas Volf, Maxime Devos, Nala Ginrut
From 302159fe61d9df526911ead8ea6ad823ad8b0443 Mon Sep 17 00:00:00 2001
From: AwesomeAdam54321 <adam.faiz@disroot.org>
Date: Sun, 15 Dec 2024 23:48:30 +0800
Subject: [PATCH 1/2] rdelim: Add new procedure `for-rdelim-in-port`.
* module/ice-9/rdelim.scm (for-rdelim-in-port): Add it.
(for-delimited-in-port): Define as a specialised `for-rdelim-in-port`.
(for-line-in-file): Define as a specialised `for-delimited-in-port`.
These procedures provide a backbone for parsing, with domain-specific
logic implemented as a separate procedure to be passed as an argument.
---
module/ice-9/rdelim.scm | 35 ++++++++++++++++++++++++++++++++++-
1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/module/ice-9/rdelim.scm b/module/ice-9/rdelim.scm
index d2cd081d7..0bbaaf904 100644
--- a/module/ice-9/rdelim.scm
+++ b/module/ice-9/rdelim.scm
@@ -23,7 +23,10 @@
;;; similar to (scsh rdelim) but somewhat incompatible.
(define-module (ice-9 rdelim)
- #:export (read-line
+ #:export (for-delimited-in-port
+ for-line-in-file
+ for-rdelim-in-port
+ read-line
read-line!
read-delimited
read-delimited!
@@ -206,3 +209,33 @@ characters to read. By default, there is no limit."
line)
(else
(error "unexpected handle-delim value: " handle-delim)))))
+
+(define* (for-rdelim-in-port port proc rdelim-proc
+ #:key (stop-pred eof-object?))
+ "Call PROC for every (RDELIM-PROC PORT) in PORT until STOP-PRED returns #t.
+RDELIM-PROC has to advance through PORT with every call."
+ (let loop ((rdelim (rdelim-proc port)))
+ (cond ((stop-pred rdelim)
+ (close-port port))
+ (else
+ (proc rdelim)
+ (loop (rdelim-proc port))))))
+
+(define* (for-delimited-in-port port proc
+ #:key (delims "\n") (handle-delim 'trim))
+ "Call PROC for every delimited line in PORT until the eof-object is reached."
+ (for-rdelim-in-port port proc
+ (lambda (port)
+ (read-delimited delims port handle-delim))))
+
+(define* (for-line-in-file file proc
+ #:key (encoding #f) (guess-encoding #f))
+ "Call PROC for every line in FILE until the eof-object is reached.
+FILE must be a filename string.
+
+The line provided to PROC is guaranteed to be a string."
+ (call-with-input-file
+ file
+ (lambda (port)
+ (for-delimited-in-port port proc))
+ #:encoding encoding #:guess-encoding guess-encoding))
--
2.41.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/2] doc: Add documentation for `for-rdelim-in-port` and, related procedures.
2024-12-16 15:21 [PATCH 1/2] rdelim: Add new procedure `for-rdelim-in-port` Adam Faiz
@ 2024-12-16 15:24 ` Adam Faiz
2024-12-17 4:31 ` [PATCH] test-suite: Add tests for `for-rdelim-in-port`-related functions Adam Faiz
2024-12-16 16:46 ` [PATCH 1/2] rdelim: Add new procedure `for-rdelim-in-port` Nala Ginrut
1 sibling, 1 reply; 7+ messages in thread
From: Adam Faiz @ 2024-12-16 15:24 UTC (permalink / raw)
To: guile-devel; +Cc: Ricardo Wurmus, Tomas Volf, Maxime Devos, Nala Ginrut
From b271d059615571d0d50027758494b8dbb5e8625e Mon Sep 17 00:00:00 2001
From: AwesomeAdam54321 <adam.faiz@disroot.org>
Date: Mon, 16 Dec 2024 22:55:41 +0800
Subject: [PATCH 2/2] doc: Add documentation for `for-rdelim-in-port` and
related procedures.
* doc/ref/api-io.texi (for-rdelim-in-port): Document API.
(for-delimited-in-port): Likewise.
(for-line-in-file): Likewise.
---
doc/ref/api-io.texi | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/doc/ref/api-io.texi b/doc/ref/api-io.texi
index 79bc9e9d6..23e316c27 100644
--- a/doc/ref/api-io.texi
+++ b/doc/ref/api-io.texi
@@ -984,6 +984,28 @@ used. This procedure is equivalent to:
@end lisp
@end deffn
+@deffn {Scheme Procedure} for-rdelim-in-port port proc rdelim-proc @
+ [#:stop-pred=eof-object?]
+For every unit provided by @code{(rdelim-proc port)}, provide
+this unit(rdelim) to @var{proc} to be processed. This will continue throughout
+@var{port} until @var{stop-pred} returns @code{#t}.
+@var{stop-pred} is @code{eof-object?} by default.
+@var{rdelim-proc} has to advance through @var{port} with every call made to it.
+@end deffn
+
+@deffn {Scheme Procedure} for-delimited-in-port port proc @
+ [#:delims=''\n''] [#:handle-delim='trim]
+Call @var{proc} for every line delimited by @var{delims} in @var{port}.
+@end deffn
+
+@deffn {Scheme Procedure} for-line-in-file file proc @
+ [#:encoding=#f] [#:guess-encoding=#f]
+Call @var{proc} for every line in @var{file}.
+@var{file} must be a filename string.
+
+The line provided to @var{proc} is guaranteed to be a string.
+@end deffn
+
@node Default Ports
@subsection Default Ports for Input, Output and Errors
@cindex Default ports
--
2.41.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] rdelim: Add new procedure `for-rdelim-in-port`.
2024-12-16 15:21 [PATCH 1/2] rdelim: Add new procedure `for-rdelim-in-port` Adam Faiz
2024-12-16 15:24 ` [PATCH 2/2] doc: Add documentation for `for-rdelim-in-port` and, related procedures Adam Faiz
@ 2024-12-16 16:46 ` Nala Ginrut
1 sibling, 0 replies; 7+ messages in thread
From: Nala Ginrut @ 2024-12-16 16:46 UTC (permalink / raw)
To: Adam Faiz; +Cc: guile-devel, Ricardo Wurmus, Tomas Volf, Maxime Devos
[-- Attachment #1: Type: text/plain, Size: 3284 bytes --]
Thanks for the work!
I didn’t find anything to be picky about yet in the implementation.
Now there are two things could go further.
1. About the port closing, I don’t insist on my previous suggestion right
now. There may be arguments against it by folks. I’m fine with any.
2. To complete a promising patch, it’s better to have test cases. You may
take a look at the existing tests to learn how.
Best regards.
On Reiwa 6 Dec 17, Tue at 0:22 Adam Faiz <adam.faiz@disroot.org> wrote:
> From 302159fe61d9df526911ead8ea6ad823ad8b0443 Mon Sep 17 00:00:00 2001
> From: AwesomeAdam54321 <adam.faiz@disroot.org>
> Date: Sun, 15 Dec 2024 23:48:30 +0800
> Subject: [PATCH 1/2] rdelim: Add new procedure `for-rdelim-in-port`.
>
> * module/ice-9/rdelim.scm (for-rdelim-in-port): Add it.
> (for-delimited-in-port): Define as a specialised `for-rdelim-in-port`.
> (for-line-in-file): Define as a specialised `for-delimited-in-port`.
>
> These procedures provide a backbone for parsing, with domain-specific
> logic implemented as a separate procedure to be passed as an argument.
> ---
> module/ice-9/rdelim.scm | 35 ++++++++++++++++++++++++++++++++++-
> 1 file changed, 34 insertions(+), 1 deletion(-)
>
> diff --git a/module/ice-9/rdelim.scm b/module/ice-9/rdelim.scm
> index d2cd081d7..0bbaaf904 100644
> --- a/module/ice-9/rdelim.scm
> +++ b/module/ice-9/rdelim.scm
> @@ -23,7 +23,10 @@
> ;;; similar to (scsh rdelim) but somewhat incompatible.
>
> (define-module (ice-9 rdelim)
> - #:export (read-line
> + #:export (for-delimited-in-port
> + for-line-in-file
> + for-rdelim-in-port
> + read-line
> read-line!
> read-delimited
> read-delimited!
> @@ -206,3 +209,33 @@ characters to read. By default, there is no limit."
> line)
> (else
> (error "unexpected handle-delim value: " handle-delim)))))
> +
> +(define* (for-rdelim-in-port port proc rdelim-proc
> + #:key (stop-pred eof-object?))
> + "Call PROC for every (RDELIM-PROC PORT) in PORT until STOP-PRED returns
> #t.
> +RDELIM-PROC has to advance through PORT with every call."
> + (let loop ((rdelim (rdelim-proc port)))
> + (cond ((stop-pred rdelim)
> + (close-port port))
> + (else
> + (proc rdelim)
> + (loop (rdelim-proc port))))))
> +
> +(define* (for-delimited-in-port port proc
> + #:key (delims "\n") (handle-delim 'trim))
> + "Call PROC for every delimited line in PORT until the eof-object is
> reached."
> + (for-rdelim-in-port port proc
> + (lambda (port)
> + (read-delimited delims port handle-delim))))
> +
> +(define* (for-line-in-file file proc
> + #:key (encoding #f) (guess-encoding #f))
> + "Call PROC for every line in FILE until the eof-object is reached.
> +FILE must be a filename string.
> +
> +The line provided to PROC is guaranteed to be a string."
> + (call-with-input-file
> + file
> + (lambda (port)
> + (for-delimited-in-port port proc))
> + #:encoding encoding #:guess-encoding guess-encoding))
> --
> 2.41.0
>
[-- Attachment #2: Type: text/html, Size: 4231 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH] test-suite: Add tests for `for-rdelim-in-port`-related functions.
2024-12-16 15:24 ` [PATCH 2/2] doc: Add documentation for `for-rdelim-in-port` and, related procedures Adam Faiz
@ 2024-12-17 4:31 ` Adam Faiz
2024-12-17 5:11 ` Nala Ginrut
0 siblings, 1 reply; 7+ messages in thread
From: Adam Faiz @ 2024-12-17 4:31 UTC (permalink / raw)
To: guile-devel; +Cc: Ricardo Wurmus, Tomas Volf, Maxime Devos, Nala Ginrut, mikael
From 258d20a9665e6f845a167258c33374a00e734885 Mon Sep 17 00:00:00 2001
From: AwesomeAdam54321 <adam.faiz@disroot.org>
Date: Tue, 17 Dec 2024 12:20:52 +0800
Subject: [PATCH] test-suite: Add tests for `for-rdelim-in-port`-related
functions.
* test-suite/tests/ports.test: Add test cases for
`for-delimited-in-port` and `for-line-in-file`.
---
test-suite/tests/ports.test | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/test-suite/tests/ports.test b/test-suite/tests/ports.test
index bec5e356c..15d515f1f 100644
--- a/test-suite/tests/ports.test
+++ b/test-suite/tests/ports.test
@@ -2089,6 +2089,28 @@
(not (string-index (%search-load-path (basename (test-file)))
#\\))))))
+(let ((lst '())
+ (lines '())
+ (string "line1\nline2\nline3")
+ (filename (test-file)))
+ (call-with-input-string
+ "A\0B\0C"
+ (lambda (port)
+ (pass-if "for-delimited-in-port returns true upon completion"
+ (for-delimited-in-port port
+ (lambda (entry)
+ (set! lst (cons entry lst)))
+ #:delims "\0")
+ (equal? lst '("C" "B" "A")))))
+ (let ((port (open-output-file filename)))
+ (display string port)
+ (close-port port))
+ (pass-if "for-line-in-file returns true upon completion"
+ (for-line-in-file filename
+ (lambda (line)
+ (set! lines (cons line lines))))
+ (equal? lines '("line3" "line2" "line1"))))
+
(delete-file (test-file))
;;; Local Variables:
--
2.46.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] test-suite: Add tests for `for-rdelim-in-port`-related functions.
2024-12-17 4:31 ` [PATCH] test-suite: Add tests for `for-rdelim-in-port`-related functions Adam Faiz
@ 2024-12-17 5:11 ` Nala Ginrut
2024-12-17 7:21 ` Mikael Djurfeldt
0 siblings, 1 reply; 7+ messages in thread
From: Nala Ginrut @ 2024-12-17 5:11 UTC (permalink / raw)
To: Adam Faiz; +Cc: guile-devel, Ricardo Wurmus, Tomas Volf, Maxime Devos, mikael
[-- Attachment #1: Type: text/plain, Size: 2021 bytes --]
The preferred activity in your design is more like for-each family, say,
handle the result inside the proc without return result. So maybe it should
be named as for-each-*-in-file, which is more understandable in the first
glance.
Best regards.
On Tue, Dec 17, 2024, 13:31 Adam Faiz <adam.faiz@disroot.org> wrote:
> From 258d20a9665e6f845a167258c33374a00e734885 Mon Sep 17 00:00:00 2001
> From: AwesomeAdam54321 <adam.faiz@disroot.org>
> Date: Tue, 17 Dec 2024 12:20:52 +0800
> Subject: [PATCH] test-suite: Add tests for `for-rdelim-in-port`-related
> functions.
>
> * test-suite/tests/ports.test: Add test cases for
> `for-delimited-in-port` and `for-line-in-file`.
> ---
> test-suite/tests/ports.test | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/test-suite/tests/ports.test b/test-suite/tests/ports.test
> index bec5e356c..15d515f1f 100644
> --- a/test-suite/tests/ports.test
> +++ b/test-suite/tests/ports.test
> @@ -2089,6 +2089,28 @@
> (not (string-index (%search-load-path (basename (test-file)))
> #\\))))))
>
> +(let ((lst '())
> + (lines '())
> + (string "line1\nline2\nline3")
> + (filename (test-file)))
> + (call-with-input-string
> + "A\0B\0C"
> + (lambda (port)
> + (pass-if "for-delimited-in-port returns true upon completion"
> + (for-delimited-in-port port
> + (lambda (entry)
> + (set! lst (cons entry lst)))
> + #:delims "\0")
> + (equal? lst '("C" "B" "A")))))
> + (let ((port (open-output-file filename)))
> + (display string port)
> + (close-port port))
> + (pass-if "for-line-in-file returns true upon completion"
> + (for-line-in-file filename
> + (lambda (line)
> + (set! lines (cons line lines))))
> + (equal? lines '("line3" "line2" "line1"))))
> +
> (delete-file (test-file))
>
> ;;; Local Variables:
> --
> 2.46.0
>
[-- Attachment #2: Type: text/html, Size: 2838 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] test-suite: Add tests for `for-rdelim-in-port`-related functions.
2024-12-17 5:11 ` Nala Ginrut
@ 2024-12-17 7:21 ` Mikael Djurfeldt
2024-12-17 16:43 ` Mikael Djurfeldt
0 siblings, 1 reply; 7+ messages in thread
From: Mikael Djurfeldt @ 2024-12-17 7:21 UTC (permalink / raw)
To: Nala Ginrut
Cc: Adam Faiz, guile-devel, Ricardo Wurmus, Tomas Volf, Maxime Devos
[-- Attachment #1: Type: text/plain, Size: 2282 bytes --]
Do others think this as well? To me, the shorter names which Adam selected
seem more palatable. Otherwise they get a bit long.
Den tis 17 dec. 2024 06:11Nala Ginrut <nalaginrut@gmail.com> skrev:
> The preferred activity in your design is more like for-each family, say,
> handle the result inside the proc without return result. So maybe it should
> be named as for-each-*-in-file, which is more understandable in the first
> glance.
> Best regards.
>
> On Tue, Dec 17, 2024, 13:31 Adam Faiz <adam.faiz@disroot.org> wrote:
>
>> From 258d20a9665e6f845a167258c33374a00e734885 Mon Sep 17 00:00:00 2001
>> From: AwesomeAdam54321 <adam.faiz@disroot.org>
>> Date: Tue, 17 Dec 2024 12:20:52 +0800
>> Subject: [PATCH] test-suite: Add tests for `for-rdelim-in-port`-related
>> functions.
>>
>> * test-suite/tests/ports.test: Add test cases for
>> `for-delimited-in-port` and `for-line-in-file`.
>> ---
>> test-suite/tests/ports.test | 22 ++++++++++++++++++++++
>> 1 file changed, 22 insertions(+)
>>
>> diff --git a/test-suite/tests/ports.test b/test-suite/tests/ports.test
>> index bec5e356c..15d515f1f 100644
>> --- a/test-suite/tests/ports.test
>> +++ b/test-suite/tests/ports.test
>> @@ -2089,6 +2089,28 @@
>> (not (string-index (%search-load-path (basename (test-file)))
>> #\\))))))
>>
>> +(let ((lst '())
>> + (lines '())
>> + (string "line1\nline2\nline3")
>> + (filename (test-file)))
>> + (call-with-input-string
>> + "A\0B\0C"
>> + (lambda (port)
>> + (pass-if "for-delimited-in-port returns true upon completion"
>> + (for-delimited-in-port port
>> + (lambda (entry)
>> + (set! lst (cons entry lst)))
>> + #:delims "\0")
>> + (equal? lst '("C" "B" "A")))))
>> + (let ((port (open-output-file filename)))
>> + (display string port)
>> + (close-port port))
>> + (pass-if "for-line-in-file returns true upon completion"
>> + (for-line-in-file filename
>> + (lambda (line)
>> + (set! lines (cons line lines))))
>> + (equal? lines '("line3" "line2" "line1"))))
>> +
>> (delete-file (test-file))
>>
>> ;;; Local Variables:
>> --
>> 2.46.0
>>
>
[-- Attachment #2: Type: text/html, Size: 3341 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] test-suite: Add tests for `for-rdelim-in-port`-related functions.
2024-12-17 7:21 ` Mikael Djurfeldt
@ 2024-12-17 16:43 ` Mikael Djurfeldt
0 siblings, 0 replies; 7+ messages in thread
From: Mikael Djurfeldt @ 2024-12-17 16:43 UTC (permalink / raw)
To: Nala Ginrut
Cc: Adam Faiz, guile-devel, Ricardo Wurmus, Tomas Volf, Maxime Devos
[-- Attachment #1: Type: text/plain, Size: 3316 bytes --]
I think these procedures are handy in common situations. There has been a
discussion about generalization. I have the feeling that such
generalization either already exists in some SRFI or that one should put
some deep thinking into how to represent flexible iteration in Scheme.
I don't think it would be bad to apply Adam's patch, though, or that
placing it in (ice-9 rdelim) is unnatural.
If no one objects, I will apply the patch in a couple of days with the
current naming scheme but modified by the following:
I think "in-port" is redundant and slightly confusing and ambiguous (c.f.
"input") and would replace it with "from-port" to conform with other
procedure names (such as with-input-from-port). On the other hand,
"line-in-file" feels natural despite the existence of with-input-from-file.
On Tue, Dec 17, 2024 at 8:21 AM Mikael Djurfeldt <mikael@djurfeldt.com>
wrote:
> Do others think this as well? To me, the shorter names which Adam selected
> seem more palatable. Otherwise they get a bit long.
>
> Den tis 17 dec. 2024 06:11Nala Ginrut <nalaginrut@gmail.com> skrev:
>
>> The preferred activity in your design is more like for-each family, say,
>> handle the result inside the proc without return result. So maybe it should
>> be named as for-each-*-in-file, which is more understandable in the first
>> glance.
>> Best regards.
>>
>> On Tue, Dec 17, 2024, 13:31 Adam Faiz <adam.faiz@disroot.org> wrote:
>>
>>> From 258d20a9665e6f845a167258c33374a00e734885 Mon Sep 17 00:00:00 2001
>>> From: AwesomeAdam54321 <adam.faiz@disroot.org>
>>> Date: Tue, 17 Dec 2024 12:20:52 +0800
>>> Subject: [PATCH] test-suite: Add tests for `for-rdelim-in-port`-related
>>> functions.
>>>
>>> * test-suite/tests/ports.test: Add test cases for
>>> `for-delimited-in-port` and `for-line-in-file`.
>>> ---
>>> test-suite/tests/ports.test | 22 ++++++++++++++++++++++
>>> 1 file changed, 22 insertions(+)
>>>
>>> diff --git a/test-suite/tests/ports.test b/test-suite/tests/ports.test
>>> index bec5e356c..15d515f1f 100644
>>> --- a/test-suite/tests/ports.test
>>> +++ b/test-suite/tests/ports.test
>>> @@ -2089,6 +2089,28 @@
>>> (not (string-index (%search-load-path (basename (test-file)))
>>> #\\))))))
>>>
>>> +(let ((lst '())
>>> + (lines '())
>>> + (string "line1\nline2\nline3")
>>> + (filename (test-file)))
>>> + (call-with-input-string
>>> + "A\0B\0C"
>>> + (lambda (port)
>>> + (pass-if "for-delimited-in-port returns true upon completion"
>>> + (for-delimited-in-port port
>>> + (lambda (entry)
>>> + (set! lst (cons entry lst)))
>>> + #:delims "\0")
>>> + (equal? lst '("C" "B" "A")))))
>>> + (let ((port (open-output-file filename)))
>>> + (display string port)
>>> + (close-port port))
>>> + (pass-if "for-line-in-file returns true upon completion"
>>> + (for-line-in-file filename
>>> + (lambda (line)
>>> + (set! lines (cons line lines))))
>>> + (equal? lines '("line3" "line2" "line1"))))
>>> +
>>> (delete-file (test-file))
>>>
>>> ;;; Local Variables:
>>> --
>>> 2.46.0
>>>
>>
[-- Attachment #2: Type: text/html, Size: 4665 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2024-12-17 16:43 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-16 15:21 [PATCH 1/2] rdelim: Add new procedure `for-rdelim-in-port` Adam Faiz
2024-12-16 15:24 ` [PATCH 2/2] doc: Add documentation for `for-rdelim-in-port` and, related procedures Adam Faiz
2024-12-17 4:31 ` [PATCH] test-suite: Add tests for `for-rdelim-in-port`-related functions Adam Faiz
2024-12-17 5:11 ` Nala Ginrut
2024-12-17 7:21 ` Mikael Djurfeldt
2024-12-17 16:43 ` Mikael Djurfeldt
2024-12-16 16:46 ` [PATCH 1/2] rdelim: Add new procedure `for-rdelim-in-port` Nala Ginrut
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).