Path: ...!2.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: "B. Pym" Newsgroups: comp.lang.lisp,comp.lang.scheme Subject: Re: String processing Date: Thu, 19 Sep 2024 06:23:59 -0000 (UTC) Organization: A noiseless patient Spider Lines: 77 Message-ID: References: MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Injection-Date: Thu, 19 Sep 2024 08:23:59 +0200 (CEST) Injection-Info: dont-email.me; posting-host="25924006d51a03bad00818fb787899cc"; logging-data="508135"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18fBimhP7dqezhqL/Ye/7oI" User-Agent: XanaNews/1.18.1.6 Cancel-Lock: sha1:7vMqUY6IueiqgSvSN60hviDjMMc= Bytes: 3347 B. Pym wrote: > Pierre Mai wrote: > > > > We've had this discussion before. Perl was designed to make file scanning > > > and pattern matching easy. The programs we've been designing in this > > > thread are precisely the kind of application that Perl is intended for. > > > I'm well-enough versed in Lisp to know that the equivalent of: > > > > > > while (<>) { # Loop over input lines > > > counter++ if /^\s*\(/; # if first non-white character is open-paren, count i > > t > > > } > > > > > > would be much more verbose without being significantly more expressive. > > ------------- > > > > If it weren't for the regexp, which needs a comment of 10 words to > > explain what it does, and which is easy to get wrong (either comment, > > or regexp that is), I could believe that statement, but so I have to > > humbly disagree ;) > > > > Anyways, this is Common Lisp: > > > > (loop for line = (read-line *standard-input* nil nil) > > while line > > count (starts-with (left-trim-whitespace line) "(")) > > > > This uses two trivial string functions which are probably part of > > every working CL user[1]. With an extensible LOOP facility, this could > > even be clarified further... > .... > > Footnotes: > > [1] Here are some very simple, inefficient sample implementations: > > (defun starts-with (string substring) > > "Detect whether the `string' starts with `substring'." > > (eql 0 (search substring string))) > > > > (defun left-trim-whitespace (string &optional (ws-bag '(#\Space #\Tab))) > > "Trims any whitespace characters (i.e. characters in `ws-bag') from > > the left side of `string'." > > (string-left-trim ws-bag string)) > > Gauche Scheme > > (use gauche.generator) > > Using a regular expression: > > (generator-count #/^\s*[(]/ read-line) > > Without using a regular expression: > > (use srfi-13) ;; string-trim string-prefix? > > (generator-count (^s (string-prefix? "(" (string-trim s))) read-line) Another way. (generator-count (=>> string-trim (string-prefix? "(")) read-line) Given: (define-syntax ->> (syntax-rules () [(_ x) x] [(_ x (y ...) z ...) (->> (y ... x) z ...)] [(_ x y z ...) (->> (y x) z ...)])) ;; currying (define-syntax =>> (syntax-rules () [(_ func ...) (lambda (x) (->> x func ...))]))