4 ms·
It's not just the parentheses. It's the whole code-as-data and interactive development thing. Code is different. Programming is different. Lisp uses different
by lispm 10y ago
It's not just the parentheses. It's the whole code-as-data and interactive development thing. Code is different. Programming is different.
Lisp uses different working styles and tools. You have to learn the whole set. It's possible to learn that and to learn it well, but it might take some time.
Lisp code can be very readable, but it's also to write very complex code - more complex that in most languages, since Lisp provides many mechanisms under developer control.
- kazinator 10y agoEven if you don't care about using code as data, Lisp is simply more readable, period. You don't have to crack open a reference manual to look at grammar rules or precedence tables to work out what the shape of the syntax tree is; you can read anything just from the symbolic prefix, plus a smattering of minor notations like sharpsign-this and sharpsign-that. A programmer who doesn't know Lisp can still instinctively tell that in (foo (x y) (z w)), the x and y go together more tightly than foo and x, or y and z. The meaning is determined by foo. But foo is a word. And words have the nice property that you can look them up easily in manuals (potentially with just a mouse click). Those who say Lisp is not readable are trolls and liars. They are liars because they see it's obviously more readable, but it threatens their self-image of being a competent programmer. It does that because their self-image is rooted in having memorized a bunch of arcane syntax and believing that that is what makes a software developer. Look at this comment, for instance: https://news.ycombinator.com/item?id=12883362 https://news.ycombinator.com/item?id=12883362 "If only the LISP syntax looked like a programming language and made logical sense." Very good representative comment which captures the mindset aptly. A programming language can only possibly be legit only if programs in that look like what you already know.
- lispm 10y ago> You don't have to crack open a reference manual to look at grammar rules or precedence tables to work out what the shape of the syntax tree is; you can read anything just from the symbolic prefix, plus a smattering of minor notations like sharpsign-this and sharpsign-that. You can't. Any macro may support arbitrary syntax. If all you know is the macro name, you don't know nothing about the syntax it implements. > (foo (x y) (z w)) There are many many much more complex forms in Lisp. > And words have the nice property that you can look them up easily in manuals Then you have to read the syntax FOO implements. DEFGENERIC: defgeneric function-name gf-lambda-list [[option | {method-description}*]] => new-generic option::= (:argument-precedence-order parameter-name+) | (declare gf-declaration+) | (:documentation gf-documentation) | (:method-combination method-combination method-combination-argument*) | (:generic-function-class generic-function-class) | (:method-class method-class) method-description::= (:method method-qualifier* specialized-lambda-list [[declaration* | documentation]] form*) Then you need to know the set of precedence order names. What is a GF-DECLARACTION? What is a method-qualifier? what is the specialized-lambda-list? What are valid declaration expressions...? > Those who say Lisp is not readable are trolls and liars. I don't think you add credibility with these statements. Sorry, this is just dumb.
- kazinator 10y ago(defgeneric draw (thing on-what where)) (defmethod draw ((obj drawable) (where canvas) (location point)) ...) No brainer. Even though macros can contain any syntax, and in principle we can have a macro such that: (mac token1 token2 token3 ... tokenN) where the tokens are parsed according to some LALR(1) (or worse) grammar, in practice, macros are usually not designed that way. The nested list syntax is used for grouping units together. So without knowing what mac is, you don't know the semantics, but the structure is, more often than not, crystal clear. Of course you need the manual to know what they mean if you don't remember (gee, which is the class name and which is the instance, location or point?), but you don't have to implement the LARL(1) parser in your head.
- lispm 10y ago> No brainer. I was talking about DEFGENERIC syntax, not a trivial example of DEFGENERIC/DEFMETHOD. > Even though macros can contain any syntax...practice, macros are usually not designed that way. The LOOP and ITERATE macros are examples of macros with lots of syntax. > So without knowing what mac is, you don't know the semantics, but the structure is, more often than not, crystal clear. The syntax of DECLARE, DEFGENERIC, HANDLER-CASE, HANDLER-BIND, DEFINE-CONDITION, DEFINE-METHOD-COMBINATION, LOOP, FORMAT, ... are far from 'crystal clear'. One of the macros which is very hard to get right and to understand what it actually does is CLIM:DEFINE-APPLICATION-FRAME Example: (define-application-frame pets (command-queue-mixin standard-application-frame) ((assembly-group :initform nil :accessor pets-assembly-group) (current-sheet :initform nil :accessor pets-current-sheet) (show-sheet-backgrounds-p :initform t :initarg :show-sheet-backgrounds-p :accessor pets-show-sheet-backgrounds-p) (edit-mode-p :initform t :initarg :edit-mode-p :accessor pets-edit-mode-p) (current-prototype-element-class :initform nil :accessor pets-current-prototype-element-class) (blue-elements :initform nil :accessor pets-blue-elements) (red-elements :initform nil :accessor pets-red-elements) (orange-elements :initform nil :accessor pets-orange-elements) (prototype-vector :initform nil :accessor pets-frame-prototype-vector) (scaling-factor :initform 1 :accessor pets-scaling-factor) (scaling-factor-changed-p :initform nil :accessor pets-scaling-factor-changed-p) (rectification-p :initform t :accessor pets-rectification-p) (elements-to-be-checked :initform nil :accessor pets-elements-to-be-checked) (viewport-position :initform nil :accessor pets-frame-viewport-position)) ;;(:pointer-documentation t) (:command-table (pets :inherit-from (pets-assembly-group-commands pets-sheet-commands pets-measurement-commands pets-configuration-commands) :menu (("Assembly" :menu pets-assembly-group-commands :documentation "Assembly Commands") ("Sheet" :menu pets-sheet-commands :documentation "Sheet Commands") ("Configuration" :menu pets-configuration-commands :documentation "Configuration Commands") ("Generator" :menu pets-measurement-commands :documentation "Test Plan Genenerator Commands")))) (:panes (prototype-elements-pane :application :display-function 'draw-circuit-elements-with-descriptor :incremental-redisplay t :max-width +prototype-elements-pane-width+ :min-width +prototype-elements-pane-width+ :width +prototype-elements-pane-width+ :scroll-bars nil) (relay-state-pane :accept-values :text-style (make-text-style :fix :roman :normal) :max-width +relay-state-pane-width+ :min-width +relay-state-pane-width+ :width +relay-state-pane-width+ :scroll-bars :vertical :display-function '(accept-values-pane-displayer :displayer draw-relay-states-avv :resynchronize-every-pass t)) (circuit-pane :application :display-function 'draw-circuit :output-record (make-instance 'r-tree-output-history) :min-height 200 :incremental-redisplay t) (command-listener :interactor :min-height 100 :height 100 :max-height 100) (sheet-pane (make-pane 'option-pane :label "Current Sheet" :value 1 :items '(1) :value-changed-callback 'change-current-sheet)) (scaling-factor-options-pane (make-pane 'option-pane :label " Scaling Factor" :value 1 :items '(1/2 1 2) :value-changed-callback 'change-scaling-factor)) (background-shown-toggle-button-pane (make-pane 'toggle-button :value nil :value-changed-callback 'change-show-background-p :label "Hide Background")) (measurement-paths-pane (make-pane 'list-pane :label "Measurement Path" :name-key 'print-measurement-path :items (list *no-path-selected*) ;; :scroll-bars :both currently being ignored by CLIM :value *no-path-selected* :visible-items 39 :width 150 :min-width 150 :max-with 200 :value-changed-callback 'change-measurement-path)) (attribute-pane (make-clim-stream-pane ;;:foreground +white+ ;;:background +black+ :text-style (make-text-style :sans-serif :bold :small) :scroll-bars nil :min-height '(1 :line) :max-height '(1 :line) :height '(1 :line))) (pointer-documentation (make-clim-stream-pane :foreground +white+ :background +black+ :text-style (make-text-style :sans-serif :bold :small) :type 'pointer-documentation-pane :scroll-bars nil :min-height '(1 :line) :max-height '(1 :line) :height '(1 :line)))) (:layouts (data-input (vertically () (horizontally () prototype-elements-pane circuit-pane) (horizontally () command-listener (vertically () (horizontally () sheet-pane scaling-factor-options-pane) (horizontally (:max-width 150) background-shown-toggle-button-pane))) pointer-documentation attribute-pane)) (test-plan-generation (vertically () (horizontally () relay-state-pane circuit-pane (scrolling () measurement-paths-pane)) (horizontally () command-listener (vertically () (horizontally () sheet-pane scaling-factor-options-pane) (horizontally (:max-width 150) background-shown-toggle-button-pane))) pointer-documentation attribute-pane)))) Here is another example: (define-application-frame stereo-demo () ;; Displays the stereo icons, and interacts with classic to build a ;; rack display. Use the more compact display method for the icons. ((rack-window-width :initform 680 :accessor rack-window-width) (rack-window-ht :initform 525 :accessor rack-window-ht) (cur-concept-rack-width :initform 10 :accessor cur-concept-rack-width) (concept-rack-zero-y :initform 530 :accessor concept-rack-zero-y) (concept-rack-zero-x :initform 10 :accessor concept-rack-zero-x) ;; There is an invisible horizontal error rack. It starts at pixel 10, ;; and grows from left to right. (cur-error-rack-width :initform 10 :accessor cur-error-rack-width) ;; absolute x posn (cur-error-overflow-rack-width :initform 10 :accessor cur-error-overflow-rack-width) ;; absolute x posn (max-error-rack-width :initform 670 :accessor max-error-rack-width) ;; (error-rack-ht :initform 100 :accessor error-rack-ht) ;; the distance between the 2 racks. ;; 100 is needed in case it is a speaker. Turntable is also larger, but the avg is 55. (error-rack-zero-y :initform 10 :accessor error-rack-zero-y) ;; y posn of top of icons (error-overflow-rack-zero-y :initform 110 ;; 65 :accessor error-overflow-rack-zero-y) ;; y posn of 2nd row of icons (error-rack-zero-x :initform 10 :accessor error-rack-zero-x) ;; leftmost posn of error racks (stereo-system :initform nil :accessor stereo-system) (graph-frame :initform nil :accessor graph-frame) ;; (graph-root :initform 'user::electrical-consumer-thing :accessor graph-root) (graph-roots :initform '(user::electrical-consumer-thing) :accessor graph-roots) (graph-left :initform 500 :accessor graph-left) (graph-top :initform 150 :accessor graph-top) (graph-width :initform 500 :accessor graph-width) (graph-height :initform 500 :accessor graph-height) (graph-orientation :initform ':horizontal :accessor graph-orientation) (non-interesting-concept-names :initform '(user::actual-component) :accessor non-interesting-concept-names) (error-overflow-rack-presentation ;; No presentation for this, just T or nil, depending on whether :initform nil :accessor error-overflow-rack-presentation) ;; we have started the error overflow rack ;; *A NEW SLOT: USE TO STORE ALL RACK PRESENTATIONS (rack-presentations :initform nil :accessor rack-presentations) ;; *A NEW SLOT: USE TO STORE THE CURRENT RACK (cur-rack :initform nil :accessor cur-rack) ;; *A NEW SLOT: USE TO STORE THE PRESENTATION OF THE CURRENT RACK (cur-rack-presentation :initform nil :accessor cur-rack-presentation) (concept-rack-presentations :initform nil :accessor concept-rack-presentations) (error-info-presentations :initform nil :accessor error-info-presentations) (explanations :initform nil :accessor explanations) (last-display-fn-used ;; for efficiency, keep track of the display-fn that was used to ;; display the last object, to store in the presentation-info slot. :initform nil :accessor last-display-fn-used) (last-display-x-used :initform nil :accessor last-display-x-used) (last-display-y-used :initform nil :accessor last-display-y-used) ) ;; Try to make certain cmds more general, so stereo-demo-command-table ;; can inherit from other cmd table. (:command-table (stereo-demo-command-table :inherit-from (general-interface-command-table) ;;(user-command-table) :inherit-menu t )) (:menu-bar nil) (:panes (icons :application ;; :label "Icons" ;; :width 370 ;; 300 ;; :height 340 :min-height 340 :max-height 340 :text-style '(:sans-serif :roman :small) :text-cursor nil :display-function 'draw-icon-display :display-after-commands nil :default-view 'icon-view :scroll-bars nil ;;:vertical :background *my-light-blue* :foreground +black+ ) (object-display :application ;; :label "Object Display" ;; :width 370 ;; :height 350 :min-height 350 :max-height 350 :text-style '(:fix ;;:serif :roman :small) :text-cursor nil :display-after-commands nil :end-of-page-action :allow ;; don't keep scrolling when displaying object :background *my-light-blue* :foreground +black+ :default-view 'object-display-view ) (rack :application ;; :label "Rack Display" ;; :label "Rack Display Create Complete Parts Examples Quit QUIT THIS EXAMPLE" ;; ***this was removed because it caused presentations to disappear. ;; :output-record (make-instance 'r-tree-output-history) ;; :width 680 ;; :height 525 :min-height 525 ;; :max-height 350 ;; :max-height 525 :text-style '(:serif ;;:fix :roman :very-large) ;; use this to set cmd menus to a good ;; font, but must also set the font explicitly to the below one for any drawing in the pane. ;; :text-style '(:sans-serif :roman :small) ; :text-style '(:serif :roman :small) :text-cursor nil :display-after-commands nil :default-view 'rack-view :scroll-bars nil :background *living-room-background* ;; *grey-ink* ;;+black+ ;;+white+ ;;*my-light-blue* :foreground +black+ ;;+white+ ) (error-info ;; a sideways rack containing error objects :application ;; :label "Error Info" :output-record (make-instance 'r-tree-output-history) ;; :width 680 ;; :height 350 :min-height 350 ;; :max-height 350 ;; :max-height 175 ;; :text-style '(:sans-serif :roman :small) :text-style '(:serif :roman :very-large) :text-cursor nil :display-after-commands nil :default-view 'error-view :background *my-light-pink* :foreground +black+ ) (legend :application :label "Legend" ;; :width 680 ;; :max-height 90 :text-style '(:sans-serif :roman :small) :text-cursor nil :display-function 'draw-legend :display-after-commands nil :scroll-bars nil :background *my-light-blue* :foreground +black+ ) (doc :pointer-documentation :incremental-redisplay t :text-cursor nil ; :text-style '(:sans-serif :roman :small) :text-style '(:sans-serif :roman :normal) :height 20 :min-height 20 :max-height 20 ; :background (classicist-default-background-ink) ; :foreground (fg-ink "black") :background +white+ :foreground +black+ ) (messages :application :text-cursor nil :text-style '(:sans-serif :roman :normal) ; :background (classicist-default-background-ink) ; :foreground (fg-ink "black") :background +white+ :foreground +black+ :scroll-bars nil :height 20 :min-height 20 :max-height 20 :display-after-commands nil :background +white+ :foreground +black+ ) (commands :command-menu :text-cursor nil ; :height 22 :min-height 22 :max-height 22 :height 28 :min-height 28 :max-height 28 ; :background (classicist-default-background-ink) ;; lite green, bad on ncd's? ; :foreground (fg-ink "black") :background +white+ :foreground +black+ :text-style '(:serif :roman :very-large ;; :very-large ;; :normal ;; :small )) ) ; (:geometry '(:height 740)) (:layouts (default #| (vertically () commands (horizontally () (vertically () icons object-display ) (vertically () (3/4 rack) (1/4 error-info) ; (3/4 rack) ; (1/8 error-info) ; (1/8 legend) )) doc ) |# (vertically () commands (horizontally () (390/1090 (vertically () ; (340/710 icons) ; (370/710 object-display) (310/710 icons) (400/710 object-display) )) (700/1090 (vertically () ; (3/4 rack) ; (1/4 error-info) ; (3/4 rack) ; (1/8 error-info) ; (1/8 legend) ; (.72 rack) ; (.14 error-info) ; (.14 legend) (.78 rack) (.16 error-info) (.06 legend) ))) ; doc (horizontally () (.5 doc) (.5 messages))))))