4 ms·
I think I must be really bad at communicating, because you aren't responding to any point I was trying to make. Let me try again :-) I think Racket, Scheme, a
by xscott 4y ago
I think I must be really bad at communicating, because you aren't responding to any point I was trying to make. Let me try again :-)
I think Racket, Scheme, and some Lisps are conceptually elegant, but they don't read well to people like me (or apparently the poster above).
In particular, your snippet of code has 3 different indentation strategies, and you hang your closing parens the way almost all Lisp programmers do. To me, it all looks so organic and arbitrary.
So, for those of us who don't like to read other people's Lisp - is it because of the parens? Or is it because the conventional Lisp style is alienating to us?
I really think it's the style. I'd rather read your example like:
(defun bottles-verse (n)
(flet
((bottles (:match)
((0) "No bottles")
((1) "1 bottle")
((@x) `@x bottles`)
))
(put-line
`@(bottles n) of beer on the wall\n\
@(bottles n) of beer\n\
Take one down; pass it around\n\
@(bottles (pred n)) of beer on the wall\n`
)
)
)
That's still not quite as nice as I'd like, but maybe you can see where I'm coming from.
I think most Lispers would say, "You get used to it." But, well we don't get used to it because we just stay with whatever our curly braced or indentation language is instead.
- kazinator 4y agoI write Lisp mostly in the same I write C, and the way I wrote C before learning Lisp. (Except for not closing braces on the same line; though I experimented with that style and it was fine.) printf("Hello, %s\n", get_user_name()); In C, it is common to close parentheses together though. Look at the alignment in the tm_diff function in glibc: https://sourceware.org/git/?p=glibc.git;a=blob;f=time/strftime_l.c;h=75554fee7ceff4606c81a724216e054a2cb47d44;hb=HEAD#l352 https://sourceware.org/git/?p=glibc.git;a=blob;f=time/strfti... 371 int days = (365 * years + intervening_leap_days 372 + (a->tm_yday - b->tm_yday)); 373 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) 374 + (a->tm_min - b->tm_min)) 375 + (a->tm_sec - b->tm_sec)); Vim does this alignment; I'm confident I could visually select these lines, hit = and they would stay the same. The author put extra parentheses around the initializer for days, and around the return expression. I almost certainly know the reason; doing so encourages the editor to do the alignment of the + operators with the interior of the parenthesis. Vertical alignment is important because if you violate it, it leads the eyes astray: `@(bottles) @(bottles)` Both expressions are inside the quasiliteral: they are parallel elements. Why has one de-indented, as if the literal had already closed in the previous line? There could be another argument after the quasiliteral: (put-line `@(bottles n) of beer on the wall\n\ @(bottles n) of beer\n\ Take one down; pass it around\n\ @(bottles (pred n)) of beer on the wall\n` output-stream) If you have it like this: (put-line `@(bottles n) of beer on the wall\n\ @(bottles n) of beer\n\ Take one down; pass it around\n\ @(bottles (pred n)) of beer on the wall\n` output-stream))) you're pepetrating a trompe l'oeil. The transition out of the literal is masked, making it look like output-stream is still part of the literal. I see you like four space indents, and I've used them in C in years past. Even if I wanted to experiment with four space indents in Lisp, the editor I use wouldn't support it. Believe it or not, the two space indentation is a hard-coded behavior in Vim's Lisp indent mode. Vim doesn't support the quasiliteral formatting I'm doing; I had to make the one space adjustment by hand. In short, there is almost nothing arbitrary about the way I'm formatting anything.
- xscott 4y agoWithout a doubt, C programmers have different styles. And there's disagreement about what to do when an expression gets too long. However, almost no C programmer would stack and hang their closing curly braces the way Lisp programmers do with closing parens. And for the few exceptions you'll find, they're almost certainly Lisp programmers making a point about not doing what the Romans do when they're in Rome. > In short, there is almost nothing arbitrary about the way I'm formatting anything. Heh, I didn't mean it as an attack on you. I meant it how the rest of us perceive it. Forgive me :-) I guess it's only natural that you should defend your own style. I'm just curious if maybe part of the reason Lisp is so objectionable to most programmers is because that style is so different from block structured languages. Many people here seem to like Python. So they think this is fine: def doit(n): for i in range(n): print(i) Many fewer people seem to like Lisp. So maybe this is less likeable for some reason: (def (doit n) (for i in (range n) (print i))) Ok, so is this more likeable? (def (doit n) (for i in (range n) (print i) ) ) Just curious. > Even if I wanted to experiment with four space indents in Lisp, the editor I use wouldn't support it. That's pretty circular though... Lisp programmers expect a certain indentation, so editors provide it.
- kazinator 4y ago> I guess it's only natural that you should defend your own style. I have reasons for writing things that way, that can be documented, if necessary. The style is not my own, though. > However, almost no C programmer would stack and hang their closing curly braces the way Lisp programmers do with closing parens. But they do it all the time with parentheses, which is the normal thing to do. By the way: spotted lots of this in the Zstandard compression code base a few days ago: void fun() { if (...) { for (...) { ... } } } Yikes; the closes braces line up with the opening ones, but not their corresponding matching ones. I hope that wasn't a Lisp coder (and don't suspect it). > I'm just curious if maybe part of the reason Lisp is so objectionable to most programmers is because that style is so different from block structured languages. But it isn't. Almost all the indentation and alignment strategies you see in canonically formatted Lisp code have counterparts in everyday code in mainstream languages. Found this in Linux's kernel/sched/core.c: WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&p->pi_lock) || lockdep_is_held(__rq_lockp(task_rq(p))))); ^ Lisp disease? ^ gee what is this "arbitrary" alignment? Would C be more popular if it was more typically like this? WARN_ON_ONCE( debug_locks && !( lockdep_is_held( &p->pi_lock ) || lockdep_is_held( __rq_lockp( task_rq(p) ) ) ) ); In fair.c file in the same directory: if ((ns->nr_running < ns->weight) || (((ns->compute_capacity * 100) > (ns->util * imbalance_pct)) && ((ns->compute_capacity * imbalance_pct) > (ns->runnable * 100)))) return node_has_spare; in drivers/md/raid5.c: if (s.written && (s.p_failed || ((test_bit(R5_Insync, &pdev->flags) && !test_bit(R5_LOCKED, &pdev->flags) && (test_bit(R5_UPTODATE, &pdev->flags) || test_bit(R5_Discard, &pdev->flags))))) && (s.q_failed || ((test_bit(R5_Insync, &qdev->flags) && !test_bit(R5_LOCKED, &qdev->flags) && (test_bit(R5_UPTODATE, &qdev->flags) || test_bit(R5_Discard, &qdev->flags)))))) handle_stripe_clean_event(conf, sh, disks); All of these examples use pretty much identical formatting logic as what I'm following when I'm coding in Lisp; except that a more pure version of it occurs.
- lispm 4y agoIt's more like an experienced user of a bicycle will not use stabilizer wheels. For any person who can ride a bicycle they look weird, unneccessary and actually hindering them. After a short learning phase few people will need them any more and will be happy to get rid of them. Lisp has quasi-standard indentation styles. They make code more readable and writable. The differences between Lisp and most other programming languages: Lisp code is written/read/manipulated as a data structure. What you wrote has also different indentation styles, but dangling parentheses are seen as not helpful: Lisp users don't count parentheses, they don't match parentheses like that, their code is indentation heavy, code can get very long and code can be generated. Lisp macros are an example of generated code. That means Lisp users also might look at generated code, for example when they check the code a macro generates or when one users a Lisp interpreter during debugging. The Lisp interpreter directly executes Lisp source data structures. Lisp users read by indentation of lists. The parentheses in Lisp have a different purpose as curly braces in other languages. In Lisp the parentheses are used to denote a data structure: lists. The syntax for lists (or more correct s-expressions) has its own syntax. Programs are written as nested lists of other objects. Thus the programming language Lisp is defined on top of lists. It's possible and not unusual that code is not written to a file, but generated in memory or by typing to a Lisp read-eval-print-loop, where some will directly treat the input as data, not as text. We we want to write lists as compact as possible and use indentation to make groupings visible, where necessary. The Lisp programmer learns to write/read/manipulate lists as a base. Programs are then written as lists. The usual pretty printer shows this: CL-USER 20 > (pprint '(defun bottles-verse (n) (flet ((bottles (:match) ((0) "No bottles") ((1) "1 bottle") ((@x) "@x bottles") )) (put-line foo bar) ) ) ) (DEFUN BOTTLES-VERSE (N) (FLET ((BOTTLES (:MATCH) ((0) "No bottles") ((1) "1 bottle") ((@X) "@x bottles"))) (PUT-LINE FOO BAR)))
- xscott 4y agoYou aren't telling me anything I don't already know. > Lisp [...] indentation styles. They make code more readable and writable. This is a matter of opinion, and you're free to ignore the majority or programmers who don't like Lisp. Trust me though: there are a lot of smart programmers who reject Lisp, and it's not because they "just haven't learned to ride a bike" yet. My only question is whether the people who don't like Lisp dislike it because of parens (which is the conventional wisdom) or because of the arbitrary indentation and closing brace style.
- lispm 4y ago> in particular, your snippet of code has 3 different indentation strategies, and you hang your closing parens the way almost all Lisp programmers do. To me, it all looks so organic and arbitrary. In Lisp we don't align Lisp code according to only the parentheses. A Lisp programmer looks at the symbol in front and based on that there are one or more strategies for indentation. On my Lisp Machine I can cycle through different indentations or I can completely layout the code (called 'grinding' in old Lisp). There are different lists: a definition macro (defun name (arg1 arg2) a b) a function call (foo bar baz) (foo bar baz) (foo bar baz) a special form: (if a b c) (if a b c) (when a b c) Property lists: (:name foo :age 23) and lots more. Each macro has a simple implementation style but typically an editor may have custom layout rules, depending on the macro and its syntax.