• I disagree with pretty much everything you write here, but especially this:

    First of all, you have exact same amount of parens as you would in a mainstream language like Java, C, or Js.

    My Perl example uses “mainstream language” syntax. Apparently that doesn’t count because it’s Perl (scary! mental overhead! write only!), so here’s exactly the same thing in JavaScript:

    function hypot(x, y) {    return Math.sqrt(x ** 2 + y ** 2);}
    

    … or

    const hypot = function (x, y) {    return Math.sqrt(x ** 2 + y ** 2);};
    

    … or

    const hypot = (x, y) => Math.sqrt(x ** 2 + y ** 2);
    

    Note how none of these involve four layers of nested parentheses.

    • ☆ Yσɠƚԋσʂ ☆@lemmy.mlOP
      link
      fedilink
      arrow-up
      1
      ·
      edit-2
      3 days ago

      The total number of parens in your examples is about the same, except you also have a bunch of noise like random semicolons sprinkled in. Meanwhile, nesting is a feature, not a bug because it provides you with additional visual information about relationships in code. The only people who incessantly bray about nested parens are the ones who’ve never actually worked with Lisp for any period of time. If this was a genuine problem with the syntax then stuff like sweet expressions would’ve taken off. The reality is, as I already explained and you’ve ignored, is that the editor manages the parens for you. When you work with Lisp, typing opening paren is equivalent to having a command sequence to say I’m starting a new expression.

      • Let’s take a step back. I feel this discussion has got off track a bit.

        The original claim was that Lisp’s reputation as having lots of parentheses was undeserved because it uses the same number of parens as other languages that use () for function calls; Lisp just puts the parens in a different place.

        My objection was basically that Lisp also uses parentheses for what in other languages is a declaration, a statement, a block, an operator, etc so just looking at function calls doesn’t give you the whole picture.

        You said that “Lisp” is actually a family of languages, that Clojure uses fewer parens than other Lisps (I object: still more than non-Lisps), that there are macros for infix expression syntax (I object: non-standard/3rd-party solutions that only help with operators), that parens don’t even matter because of structural editing tools (I object: irrelevant, the discussion was about the number of parens, not whether they “matter”).

        I also disagree with “the total number of parens in your examples is about the same”. This is a micro-example, so when the original Lisp (Clojure) code has 4 pairs of parens and the C-style (JavaScript, Perl) version has 2, that’s twice the parentheses to me, not “about the same”.

        I’ve tried to find a slightly bigger code sample, so I clicked around in the Clojure standard library. Here’s a chunk of clojure.string: https://github.com/clojure/clojure/blob/ade22645ba5dbf4c0d8115b19938af96d6fb4cd5/src/clj/clojure/string.clj#L275-L317

        (defn ^String trim-newline  "Removes all trailing newline \\n or return \\r characters from  string.  Similar to Perl's chomp."  {:added "1.2"}  [^CharSequence s]  (loop [index (.length s)]    (if (zero? index)      ""      (let [ch (.charAt s (dec index))]        (if (or (= ch \newline) (= ch \return))          (recur (dec index))          (.. s (subSequence 0 index) toString))))))(defn blank?  "True if s is nil, empty, or contains only whitespace."  {:added "1.2"}  [^CharSequence s]  (if s    (loop [index (int 0)]      (if (= (.length s) index)        true        (if (Character/isWhitespace (.charAt s index))          (recur (inc index))          false)))    true))(defn ^String escape  "Return a new string, using cmap to escape each character ch   from s as follows:   If (cmap ch) is nil, append ch to the new string.   If (cmap ch) is non-nil, append (str (cmap ch)) instead."  {:added "1.2"}  [^CharSequence s cmap]  (loop [index (int 0)         buffer (StringBuilder. (.length s))]    (if (= (.length s) index)      (.toString buffer)      (let [ch (.charAt s index)]        (if-let [replacement (cmap ch)]          (.append buffer replacement)          (.append buffer ch))        (recur (inc index) buffer)))))
        

        Total number of pairs of parentheses (not counting doc-strings): 45

        My translation of the code to JavaScript:

        function trim_newline(s) {    for (let index = s.length; index > 0; index--) {        let ch = s.charAt(index - 1);        if (ch != '\n' && ch != '\r') {            return s.substr(0, index);        }    }    return "";}function blank(s) {    if (s == null) {        return true;    }    for (let index = 0; index < s.length; index++) {        if (!Character.isWhitespace(s.charAt(index))) {            return false;        }    }    return true;}function escape(s, cmap) {    let buffer = "";    for (let index = 0; index < s.length; index++) {        let ch = s.charAt(index),            replacement = cmap(ch);        buffer +=            replacement !== undefined                ? replacement                : ch;    }    return buffer;}
        

        Total number of pairs of parentheses: 15

        That’s about a factor of 3. Now, you can argue that I shouldn’t care about the parentheses, but my point is simply that they’re there and you can’t really avoid them if you write in anything resembling idiomatic Lisp.

        • ☆ Yσɠƚԋσʂ ☆@lemmy.mlOP
          link
          fedilink
          arrow-up
          1
          ·
          edit-2
          2 hours ago

          You said that “Lisp” is actually a family of languages, that Clojure uses fewer parens than other Lisps (I object: still more than non-Lisps), that there are macros for infix expression syntax (I object: non-standard/3rd-party solutions that only help with operators), that parens don’t even matter because of structural editing tools (I object: irrelevant, the discussion was about the number of parens, not whether they “matter”).

          Clojure, uses different types of syntax to denote different types types of data structures, and thus different types of operations, such as statement declaration. I even gave you examples showing that you get the exact same amount of visual information as you do in other languages.

          Meanwhile, you object to the very nature of how Lisp works. The whole point Lisps is that you allow the user to easily create whatever semantics they want using macros. This is something that’s not possible to do in most languages. If you want some new semantics or syntax you have to wait for the language committee to agree on that.

          The big advantage here is that the core language can stay small and focused without having to grow over time. This is what you see happening in practically all mainstream languages. Usage patterns change, applications of the language change, and as a result new syntax continues being bolted on which makes the language ever bigger and harder to learn.

          On the other hand, with Lisp approach, you have a small language that’s simple and consistent while libraries express different semantics that happen to be needed at the time. As a user you only have to learn the semantics of the libraries used in the project you’re working on. As different patterns fall out of use, they don’t accrete within the core language. New users don’t need to know about random quirks that were popular a decade ago.

          Your second objection is also nonsensical because these is how the language used in practice. Pretty much nobody would write code without syntax highlighting, and similarly you wouldn’t use s-expressions based language without structural editing. This is a made up argument that’s a complete non sequitur. I’ve even showed you sweet expression alternative syntax that exists and literally nobody uses. If your argument had any merit to it, then that’s what Lispers would use.

          I also disagree with “the total number of parens in your examples is about the same”. This is a micro-example, so when the original Lisp (Clojure) code has 4 pairs of parens and the C-style (JavaScript, Perl) version has 2, that’s twice the parentheses to me, not “about the same”.

          const hypot = (x, y) => Math.sqrt(x ** 2 + y ** 2);
          

          4 parens, 1 ,,1 =, 1 ;, 1 =>, 1 =

          (defn hypot [x y]  (infix sqrt(x ** 2 + y ** 2)))
          

          6 parens, 1 [

          Clojure version is more consistent with less noise. Ignoring all the other noise you have to add is frankly intellectually dishonest. Whether it’s a paren or a comma, or a semicolon, an arrow or an equals sign, it’s still syntax. Clojure version has less syntax. That’s literally less stuff I need to parse visually and worry about when writing code.

          Let’s take a look at your JavaScript version more closely, and it immediately becomes obvious that you’re not actually saving anything here. You just end up sprinkling more types of control characters in it:

          9 {, 15 (, 12 = (for assignment), 16 ; 3 ,, 1 ?, :`

          That’s about a factor of 3. Now, you can argue that I shouldn’t care about the parentheses, but my point is simply that they’re there and you can’t really avoid them if you write in anything resembling idiomatic Lisp.

          Yeah if you just ignore all the other control characters you had to add instead then you sure saved on parens. Bravo!

          Your whole argument is basically treating parens as something different from other syntax characters, which is a nonsensical argument. If you’re going to compare syntax then you have to compare all the syntax you have. The only type of syntax that will give you significant reduction would be white space based syntax as seen in Python or Haskell, but that adds its own problems hence why most languages avoid it.

          • Oriel Jutty :hhHHHAAAH:@infosec.exchange
            link
            fedilink
            arrow-up
            1
            ·
            24 minutes ago

            Yeah if you just ignore all the other control characters you had to add instead then you sure saved on parens. Bravo!

            Yes! Exactly! Thank you; that was my whole point.

            Your whole argument is basically treating parens as something different from other syntax characters, which is a nonsensical argument. If you’re going to compare syntax then you have to compare all the syntax you have.

            I’m not trying to compare syntax in general. All I’m doing is refuting the original claim, which was that Lisp doesn’t use more parentheses than other (“conventional”) languages. It does.

            All that stuff about syntactic noise, granted. I mean, I don’t agree personally, but it’s irrelevant to my point.

            • ☆ Yσɠƚԋσʂ ☆@lemmy.mlOP
              link
              fedilink
              arrow-up
              1
              ·
              16 minutes ago

              Again, it’s very weird to single out one type of control character. You have to compare syntax trade offs holistically. However, even when you straight up compare parens, there isn’t a significant difference. Pretty much every language, except those using whitespace, will have two parens for arguments and curlies for the function body, or a statement. This is roughly the same number of parens you end up with in Clojure, minus all the other characters. The difference is just not that dramatic in practice.