From mboxrd@z Thu Jan 1 00:00:00 1970 From: Efraim Flashner Subject: Re: Adding wc to Bournish Date: Tue, 14 Jun 2016 13:50:37 +0300 Message-ID: <20160614105037.GC10636@debian-netbook> References: <20160524184720.GA27449@debian-netbook> <20160605124033.GB859@debian-netbook> <87eg8bpe2v.fsf@gnu.org> <20160607074155.GB32264@debian-netbook> <878tyfelf6.fsf@gnu.org> <20160614092713.GA2832@debian-netbook> <20160614102029.GB10636@debian-netbook> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="0IvGJv3f9h+YhkrH" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:43867) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bClvo-0000w4-EB for guix-devel@gnu.org; Tue, 14 Jun 2016 06:50:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bClvj-0001Ds-S7 for guix-devel@gnu.org; Tue, 14 Jun 2016 06:50:51 -0400 Received: from flashner.co.il ([178.62.234.194]:46420) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bClvj-0001DQ-FV for guix-devel@gnu.org; Tue, 14 Jun 2016 06:50:47 -0400 Content-Disposition: inline In-Reply-To: <20160614102029.GB10636@debian-netbook> List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: "Guix-devel" To: Ricardo Wurmus Cc: guix-devel@gnu.org --0IvGJv3f9h+YhkrH Content-Type: multipart/mixed; boundary="UFHRwCdBEJvubb2X" Content-Disposition: inline --UFHRwCdBEJvubb2X Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Tue, Jun 14, 2016 at 01:20:29PM +0300, Efraim Flashner wrote: > On Tue, Jun 14, 2016 at 11:57:26AM +0200, Ricardo Wurmus wrote: > >=20 > > Efraim Flashner writes: > >=20 > > > +(define wc-command-implementation > > > + (lambda files > > > + (let ((files (filter (lambda (file) > > > + (catch 'system-error > > > + (lambda () > > > + (stat file)) > > > + (lambda args > > > + (let ((errno (system-error-errno args= ))) > > > + (format (current-error-port) "~a: ~= a~%" > > > + file (strerror errno)) > > > + #f)))) > > > + files))) > > > + (for-each > > > + (lambda (file) > > > + (let-values (((lines chars) > > > + (call-with-input-file file lines+chars))) > > > + (format #t "~a ~a ~a~%" lines chars file))) > > > + files)))) > > > + > > > +(define wc-l-command-implementation > > > + (lambda files > > > + (let ((files (filter (lambda (file) > > > + (catch 'system-error > > > + (lambda () > > > + (stat file)) > > > + (lambda args > > > + (let ((errno (system-error-errno args= ))) > > > + (format (current-error-port) "~a: ~= a~%" > > > + file (strerror errno)) > > > + #f)))) > > > + files))) > > > + (for-each > > > + (lambda (file) > > > + (let-values (((lines chars) > > > + (call-with-input-file file lines+chars))) > > > + (format #t "~a ~a~%" lines file))) > > > + files)))) > > > + > > > +(define wc-c-command-implementation > > > + (lambda files > > > + (let ((files (filter (lambda (file) > > > + (catch 'system-error > > > + (lambda () > > > + (stat file)) > > > + (lambda args > > > + (let ((errno (system-error-errno args= ))) > > > + (format (current-error-port) "~a: ~a~= %" > > > + file (strerror errno)) > > > + #f)))) > > > + files))) > > > + (for-each > > > + (lambda (file) > > > + (let-values (((lines chars) > > > + (call-with-input-file file lines+chars))) > > > + (format #t "~a ~a~%" chars file))) > > > + files)))) > >=20 > > It looks to me that the filter function is the same in all of these > > procedures. Even the actual implementation, i.e. the for-each over the > > resulting files is almost exactly the same. > >=20 > > This could be simplified. If only the format expression differs then > > you could abstract this difference away. You could still have three > > different procedures, but they can be the result of evaluating a > > higher-order function. > >=20 > > It also seems to me that you could use syntactic sugar to simplify > > =E2=80=9C(define something (lambda ...))=E2=80=9D to =E2=80=9C(define (= something ...))=E2=80=9D. > >=20 > > ~~ Ricardo >=20 > It's already calling `((@@ (guix build bournish) > wc-l-command-implementation) ,@(delete "-l" args)), I could try changing > the ,@(delete part to ,@((@@ (guix build bournish) only-files) ,@(delete > "-l" args)) and then the various implementation functions will be just > printing the results >=20 It turns out I forgot that calling only-files from wc-commands would make it evaluate too soon, so I stuck it inside the different implementations. Factoring out the check if a file exists or not could also apply to the ls-command-implementation too later. --=20 Efraim Flashner =D7=90=D7=A4=D7=A8=D7=99=D7=9D = =D7=A4=D7=9C=D7=A9=D7=A0=D7=A8 GPG key =3D A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351 Confidentiality cannot be guaranteed on emails sent or received unencrypted --UFHRwCdBEJvubb2X Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="0001-bournish-Add-wc-command.patch" Content-Transfer-Encoding: quoted-printable =46rom 09eef9cd841a7d212e024be0609168611923696b Mon Sep 17 00:00:00 2001 =46rom: Efraim Flashner Date: Sun, 22 May 2016 14:56:06 +0300 Subject: [PATCH] bournish: Add `wc' command. * guix/build/bournish.scm (lines+chars, only-files, wc-commands, wc-command-implementation, wc-l-command-implementation, wc-c-command-implementation): New variables. (%commands): Add wc command. --- guix/build/bournish.scm | 58 +++++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/guix/build/bournish.scm b/guix/build/bournish.scm index 1f17e0a..a8f6591 100644 --- a/guix/build/bournish.scm +++ b/guix/build/bournish.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2016 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2016 Efraim Flashner ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,6 +26,7 @@ #:use-module (ice-9 match) #:use-module (ice-9 ftw) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) #:use-module (srfi srfi-26) #:export (%bournish-language)) =20 @@ -103,6 +105,59 @@ characters." ((@ (guix build utils) dump-port) port (current-output-port)) *unspecified*))) =20 +(define (lines+chars port) + ;; Return the number of lines and number of chars read from PORT. + ;; TODO: Also return the number of words. + (let loop ((lines 0) (chars 0)) + (match (read-char port) ; get the next char ready + ((? eof-object?) ;done! + (values lines chars)) + (#\newline ;recurse + (loop (1+ lines) (1+ chars))) + (_ ;recurse + (loop lines (1+ chars)))))) + +(define (only-files files) + (filter (lambda (file) + (catch 'system-error + (lambda () + (stat file)) + (lambda args + (let ((errno (system-error-errno args))) + (format (current-error-port) "~a: ~a~%" + file (strerror errno)) + #f)))) + files)) + +(define (wc-command-implementation . files) + (for-each + (lambda (file) + (let-values (((lines chars) + (call-with-input-file file lines+chars))) + (format #t "~a ~a ~a~%" lines chars file))) + ((@@ (guix build bournish) only-files) files))) + +(define (wc-l-command-implementation . files) + (for-each + (lambda (file) + (let-values (((lines chars) + (call-with-input-file file lines+chars))) + (format #t "~a ~a~%" lines file))) + ((@@ (guix build bournish) only-files) files))) + +(define (wc-c-command-implementation . files) + (for-each + (lambda (file) + (let-values (((lines chars) + (call-with-input-file file lines+chars))) + (format #t "~a ~a~%" chars file))) + ((@@ (guix build bournish) only-files) files))) + +(define (wc-commands . args) + (cond ((member "-l" args) `((@@ (guix build bournish) wc-l-command-imple= mentation) ,@(delete "-l" args))) + ((member "-c" args) `((@@ (guix build bournish) wc-c-command-imple= mentation) ,@(delete "-c" args))) + (else `((@@ (guix build bournish) wc-command-implementation) ,@arg= s)))) + (define (help-command . _) (display "\ Hello, this is Bournish, a minimal Bourne-like shell in Guile! @@ -129,7 +184,8 @@ commands such as 'ls' and 'cd'; it lacks globbing, pipe= s---everything.\n")) ("help" ,help-command) ("ls" ,ls-command) ("which" ,which-command) - ("cat" ,cat-command))) + ("cat" ,cat-command) + ("wc" ,wc-commands))) =20 (define (read-bournish port env) "Read a Bournish expression from PORT, and return the corresponding Sche= me --=20 2.8.4 --UFHRwCdBEJvubb2X-- --0IvGJv3f9h+YhkrH Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCgAGBQJXX+F5AAoJEPTB05F+rO6Tj+cP/3Hy8XeXhAEnN+y8uladLFPS Yxl+/+aea/VUHrY8JdooNeF2uEfL/cbvS56KpFO0AVEO0maONXJtqrYoneRC2AZn F/h4ZJLFkKPqVbn+3ohaUJ/2Sn7aalxF1FoUyyF3aydb5cOqLT2oht05V+KizeOA KWkm5u5XWOJfKF5DoeXKFoVhFWd9zDqRzcL0sOmk5OlKlF8Bo2vugzoWJVm4lO37 bY6otpaZ1UGTkEbNTO5AH42muxfhmJEPZxxY7pEnyntWyL/FFDV3yyisjUTEmKSL iHJ0w7OIHatWqgNrdggzEOJDRt3DFOTVnbI4pJC2FonPLgL/oICAAlAVfjlZOFtI EmjXivRP6BAiVNUtZFkCGjrb/QDRj6+Zqeb7O40X++CGQtAcmB9sqIjZqoJ+gfti LWY6KdWCDZXqouXsgsMM5T8OG54dGbpWYYYpLgBROPohpYFNd55LgncFQvI5NLoZ IZl9Q26pNoNC0p/tZjL1tpboVf+VS3tPh20DdtJZwCwJTEjiXksBFBumsy60BjwV ucWp3GToBYg0vpbLonMckcEesxl8vy+8GRQCa6j7KvzRUQoYULNDEcIDJFZ3VW7U ZJ8tL3ROz83zCvA55B9fk4rjeL9ZMZZEDURQE8/QwfkPxyCzjV7QTkh/4XS3prtO 7wlunHtQHBqqQ/fwbMYG =uiWu -----END PGP SIGNATURE----- --0IvGJv3f9h+YhkrH--