Coder Social home page Coder Social logo

Comments (8)

zimbatm avatar zimbatm commented on May 18, 2024

Here is anther example:

-    (prev: final: {
-      nix-build-uncached = import sources.nix-build-uncached {
-        pkgs = prev;
-      };
-      nar-serve = (import sources.nar-serve { nixpkgs = prev; }).nar-serve;
-      nixpkgs-terraform-providers = import sources.nixpkgs-terraform-providers { nixpkgs = prev; };
-    })
+    (
+      prev: final: {
+        nix-build-uncached = import sources.nix-build-uncached {
+          pkgs = prev;
+        };
+        nar-serve = (import sources.nar-serve { nixpkgs = prev; }).nar-serve;
+        nixpkgs-terraform-providers = import sources.nixpkgs-terraform-providers { nixpkgs = prev; };
+      }
+    )

from alejandra.

kamadorueda avatar kamadorueda commented on May 18, 2024

In general I see this exception as nice, we just have to be careful of cases like:

({ a
, b
}:
c)

where the { and the } are now unaligned because the parentheses displaces it 1 column to the right

on the other hand, doing this issue would introduce an incoherence between the family of brace-like elements, since the parens would be the only one to not have a newline+indent after the opening element when multiline

this also introduces some other interactions (complexity) that we need to analyze one by one

from alejandra.

zimbatm avatar zimbatm commented on May 18, 2024

Indeed. This was actually the biggest challenge with the nix syntax; there tend to be a mix and tension between aligned and Egyptian braces. I'm not sure it's possible to only have one or the other, but that surely would make things easier.

from alejandra.

DavHau avatar DavHau commented on May 18, 2024

Just throwing in the guix hello package as an example for code that never wastes extra lines with parens and still is well readable.

(use-modules (guix)
             (guix build-system gnu)
             (guix licenses))

(package
  (name "hello")
  (version "2.10")
  (source (origin
            (method url-fetch)
            (uri (string-append "mirror://gnu/hello/hello-" version
                                ".tar.gz"))
            (sha256
             (base32
              "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"))))
  (build-system gnu-build-system)
  (synopsis "Hello, GNU world: An example GNU package")
  (description "Guess what GNU Hello prints!")
  (home-page "http://www.gnu.org/software/hello/")
  (license gpl3+))

I like this, the code is readable and compact.
After I saw this, I tried to apply this concept to my nix code.
Here an example:

   packages =
     lib.mapAttrs
      (name: versions:
        lib.genAttrs
          versions
          (version:
              makePackage name version))
      packageVersions;

But alejandra currently does this:

packages =
    lib.mapAttrs
    (
      name: versions:
        lib.genAttrs
        versions
        (
          version:
            makePackage name version
        )
    )
    packageVersions;

It introduces many new lines and doesn't improve the readability in my opinion.

from alejandra.

DavHau avatar DavHau commented on May 18, 2024

Let's try to make a point out of this.

The most important thing that matters for the human eye for understanding the structure of code, is correct indentation. Brace-like elements are mostly there for the machine. A good example for underlining this point is the python language, where there are basically no brace-like elements used to structure multi line code, but instead correct indentation is enforced, which allows the machine to parse the code by indentation instead of brace-like objects. That shows that brace-like objects are not important for the human to write and understand code.

Therefore I'd argue that a code formatter should optimzie for indentation, while hiding brace-like elements as much as possible as those are not important for readability.
As a result of this, the guix way of writing code makes perfect sense to me. The indentation is kept perfect, resulting in good readability, while parens, which are only important for the parser, are kept in places where they do not occupy any extra space.

So should the never put parens in new lines philosophy become a general rule?
I think not, because we need to watch out that it doesn't introduce extra complexity when editing code.
Example where this would be the case:

Vertically aligned lists of similar elements:
#  this style is bad

[ "string1"
  ...
  "string1"
  "string3"]

In lists we often want to shift lines around, add new elements, remove elements, etc... and the fact that the first and last line start/end with different characters, makes this process more annoying.
(Same goes for argument lists, attrsets, and let..in)

If we'd apply this vertical list exception to code with nested functions this would mean:
Whenever multiple arguments are in the same line, the parenthesis can stay in the same line as well:

someFunc =
  map
    (arg1: arg2: arg3:
      doSomething arg1 arg2 arg3)

... but if arguments are split in multiple lines, the parens should move out of the way, to allow for comfortable editing:

someFunc =
  map
    (
      arg1:
      arg2:
      arg3:
        doSomething arg1 arg2 arg3
    )

This style of listing function args is probably not common, but it demonstrates how the parens in same line / next line dilemma could possibly be formed into a rule, which can be applied to any kind of brace-like objects, no matter if attrsets, lists, func args, etc.

from alejandra.

kamadorueda avatar kamadorueda commented on May 18, 2024

I think the best we can aim for is leaving the user decide when it's more readable to have it expanded, or packed

It's packed by default, and can be expanded by introducing a newline or comment after ( or before ):

Peek 2022-02-17 14-11

Solved in: #132

from alejandra.

kamadorueda avatar kamadorueda commented on May 18, 2024

This is how it looks now:

Quite nice in my opinion

from alejandra.

DavHau avatar DavHau commented on May 18, 2024

Nice results!
Though, multi-line string substitutions are still forcefully expanded:

input:

l.hashString "sha256" ''
  ${source}
  ${translator}
  ${l.toString
    (l.mapAttrsToList (k: v: "${k}=${l.toString v}") translatorArgs)}
''

alejandra result:

l.hashString "sha256" ''
  ${source}
  ${translator}
  ${
    l.toString
    (l.mapAttrsToList (k: v: "${k}=${l.toString v}") translatorArgs)
  }
''

from alejandra.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.