Package: guix-patches;
Reported by: Rostislav Svoboda <rostislav.svoboda <at> gmail.com>
Date: Sun, 15 Oct 2023 15:19:02 UTC
Severity: normal
Tags: patch
Done: Liliana Marie Prikler <liliana.prikler <at> gmail.com>
Bug is archived. No further changes may be made.
Message #26 received at 66562 <at> debbugs.gnu.org (full text, mbox):
From: Liliana Marie Prikler <liliana.prikler <at> gmail.com> To: Rostislav Svoboda <rostislav.svoboda <at> gmail.com> Cc: 66562 <at> debbugs.gnu.org Subject: Re: [PATCH v3] gnu: emacs-haskell-snippets: Use correct directory for snippets. Date: Tue, 17 Oct 2023 19:29:20 +0200
Hi, Rostislav Am Dienstag, dem 17.10.2023 um 18:49 +0200 schrieb Rostislav Svoboda: > […] > > Plus you're requiring let* instead of let. > > Having both variants is a language deficiency, in my opinion. Only > let should exist, functioning as let* does. This should extend to > lambda*, define*, etc. Only let should exist, functioning as let does. let* is sugar on top. (Not serious about this, there are reasons to have let*, but there are also reasons it's not the default behaviour.) > > Btw. don't > > ((compose > > (lambda (src dst) (mkdir-p src) (copy-recursively dst src)) > > (lambda (dir store) (values dir (string-append store "/" dir))) > > "snippets/haskell-mode" (elpa-directory (assoc-ref outputs > > "out"))) > > to avoid gratuitous repetition. > > On the one hand, we face gratuitous repetition; on the other, a > snippet like this better expresses compositional transformation > between inputs and outputs, which I find to be a way more important > that avoiding gratuitous repetition (pun intended). And as a side > effect it also simplifies debugging: > > ((compose > ;; (lambda (a b) (format #t "[DBG] 3. a: ~a; b: ~a\n" a b) (values > a b)) > (lambda (src dst) (mkdir-p src) (copy-recursively src dst)) > ;; (lambda (a b) (format #t "[DBG] 2. a: ~a; b: ~a\n" a b) (values > a b)) > (lambda (dir store) (values dir (string-append store "/" dir))) > ;; (lambda (a b) (format #t "[DBG] 1. a: ~a; b: ~a\n" a b) (values > a b)) > ) > "snippets/haskell-mode" (elpa-directory (assoc-ref outputs "out"))) If you need to warp your head around through three debug statements, I'm not convinced you're improving the overall code all that much. > And if you insist, the gratuitous repetition could, in theory, be > avoided: > > ((compose > copy-recursively > (juxt mkdir-p (partial string-append (elpa-directory (assoc-ref > outputs "out")) "/"))) > "snippets/haskell-mode") > > Only if partial and juxt would exist... and here you go ;-) > > (define (partial fun . args) > "Partial function application." > (lambda x (apply fun (append args x)))) > > (define (juxt . fns) > "Naive implementation. Inspired by Clojure's juxt. > ((juxt a b c) x) => (list (a x) (b x) (c x))" > (lambda args > (map (lambda (fn) (apply fn args)) fns))) > > Here yet another pattern appears, the map-reduce. Also the juxt > function just screams for "let's call the mkdir-p and (partial > string-append ...) in parallel". You can do all that, but it does go against the KISS principle :) > > Btw. don't (compose ...) > > Quite the contrary, I think we should do more of (compose ...), > however functional composition is hard-to-impossible if e.g.: > > - essential higher order functions like juxt and partial are not > available. We have partial. We call it cut. It's part of SRFI-26. It even simplifies the definition of juxt: (lambda args (map (cut apply <> args) fns)) Anyhow, we quite often don't use it because we'd have to add it to #:modules and the benefit over raw lambdas is often negligible. > - mkdir-p and copy-recursively from the (guix build utils) aren't > monadic and mkdir-p returns #t instead of a path-string and > copy-recursively returns: > > scheme@(guile-user)> ,use (guix build utils) > scheme@(guile-user)> (copy-recursively "/tmp/f1.txt" "/tmp/f2.txt") > `/tmp/foo.txt' -> `/tmp/fox.txt' > > eeeh... what exactly is the return value of copy-recursively? Hmm. It returns *unspecified*. Yes, most of this stuff is indeed not monadic. Scheme is not purely functional, so side effects are allowed :) > - copy-recursively, although naturally a reducer (i.e. a member of > the fold-family, think of 'a list of things goes into a container') > is not implemented as such. Hmm, disappointing... although a <...>- > fold is used in its implementation. Double hmm. There is a cost to constructing the return value of a fold. I personally can do without creating lists that no one will end up inspecting anyway. > - in general, the built-in compose function can't be called with zero > arguments. For that purpose I cobbled myself: > > (define (comp . fns) > "Like `compose'. Can be called with zero arguments. I.e. (thunk? > comp) => #t > Works also for functions returning and accepting multiple values." > (lambda args > (if (null? fns) > (apply values args) > (let [(proc (car fns)) (rest (cdr fns))] > (if (null? rest) > (apply proc args) > (let ((g (apply comp rest))) > (call-with-values (lambda () (apply g args)) > proc))))))) I'd argue that compose without procedures is quite meaningless, but maybe I'm thinking too hard. > And finally, in the (guix build utils) there's the install-file which > works with single files. What about adding its recursive version: > > (define* (install-recursively source destination > #:key > (log (current-output-port)) > (follow-symlinks? #f) > (copy-file copy-file) > keep-mtime? keep-permissions?) > "Recursive version of install-file." > (mkdir-p destination) > (copy-recursively source > (string-append destination "/" (basename > destination)) > #:log log > #:follow-symlinks? follow-symlinks? > #:copy-file copy-file > #:keep-mtime? keep-mtime? > #:keep-permissions? keep-permissions?)) There'd be no point in having copy-recursively then. For a more complete build system that already takes care of all that without having you fiddling with juxt, partial, etc., just take copy-build- system. Not that it's needed here, mind you. Cheers
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.