Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> 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.



  (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.


Here is an exercise for you:

Which of the following forms are valid Common Lisp:

    (defun foo (a b)
      (declare (fixnum a))
      "foo"
      (declare (fixnum b))
      (+ a b))

    (defun foo (a b)
      "foo"
      (declare (fixnum a))
      (declare (fixnum b))
      (+ a b))

    (defun foo (a b)
      (declare (fixnum a))
      (declare (type fixnum b))
      "foo"
      (+ a b))

    (defun foo (a b)
      (declare (type fixnum b))
      "foo"
      "bar"
      (declare (fixnum a))
      (+ a b))

    (defun foo (a b)
      (declare (fixnum a))
      (declare (type fixnum b))
      "foo"
      "bar"
      (+ a b))

    (defun foo (a b)
      (declare (fixnum a))
      "foo"
      "bar"
      (+ a b))


I don't know, and who cares.

I seem to be vaguely convinced for some reason that there may be exactly one docstring, and that, if present, it must be the first item in the body; then there can be declarations. Not sure if there can be two or more declares. I would always write (declare (fixnum a) (fixnum b)) and don't recall seeing multiple declares in other people's code. (I might be suffering from a form of amnesia which merges multiple ANSI Lisp declares into one.)

This is the sort of thing I'd look into closely if I were tasked with parsing a function body (like for the sake of making some body rearranging-and-reassembling macro fully conforming with the surrounding language). I'm not going to write such code myself, and won't likely see it in other people's code.

Until I see such instances, I won't bother looking at the spec to see what the exact rules are and confirm/refute whether those examples are conforming.

In any case, whether or not some of the examples are correct, I can see what they are trying to say. Be they mistakes, they are still well-formed surface syntax and are readable. Things could plausibly work in some CL dialect such that they are all correct, if they aren't.

A literal string near the beginning of a function, which is only evaluated for its side effect (which it doesn't have) looks suspiciously like a doc string. Either it is correctly positioned or it isn't. The (declare ...) syntax is clearly a declaration, whether or not correctly positioned. (declare ...) isn't a form. I suspect it would be undefined behavior for a program to define a function or macro called declare; not sure about that. Defined or not, it would be a incredibly bad idea.

I'm a competent Lisp programmer and implementor too, and don't have to have this memorized; it's likely not an impediment to anyone else. Which kind of makes my point.


> I don't know, and who cares.

A Lisp programmer has to care, if he wants to write Lisp code.

> I seem to be vaguely convinced for some reason that there may be exactly one docstring, and that, if present, it must be the first item in the body

That's wrong.

> I won't bother looking at the spec to see what the exact rules are

Which confirms what I'm saying: even for seemingly trivial DEFUNs the syntax is not obvious.

> Be they mistakes, they are still well-formed surface syntax and are readable.

But the reader does not implement Lisp syntax. The reader just implements s-expression syntax. If the reader can read the form, then it is a valid s-expression. But not necessarily valid Lisp.

     (defun foo (a) a)  ; valid s-expression, valid Lisp
     (defun (foo) a a)  ; valid s-expression, not valid Lisp
     (defun (bar foo) (a) a)  ; valid s-expression, not valid Lisp
     (defun (setf foo) (a) a)  ; valid s-expression, valid Lisp syntax

     (defun foo (&key a &optional b) (list a b))  ; not valid Lisp

     (defun foo ($key a &optional b) (list a b))  ; valid Lisp
The Lisp interpreter/compiler and the macros implement Lisp syntax. Not the reader.

> it's likely not an impediment to anyone else.

That you don't know the syntax of DEFUN confirms what I'm saying: the syntax is non-obvious.

Explain this:

    * (defun foo (a b)
          (declare (fixnum a))
          "foo"
          "bar"
          (+ a b))

    debugger invoked on a SIMPLE-ERROR: duplicate doc string "bar"

    Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

    restarts (invokable by number or by possibly-abbreviated name):
      0: [ABORT] Exit debugger, returning to top level.

    (SB-INT:PARSE-BODY ((DECLARE (FIXNUM A)) "foo" "bar" (+ A B)) T NIL)
    0]


> That you don't know the syntax of DEFUN confirms what I'm saying.

Yes, it rather confirms that you can go far in Lisp without memorizing stuff like this!!!

If I don't have to know, few people do.

You can bet your ass that if I had to implement an ANSI-CL conforming defun/lambda I'd get it right, of course. I don't have some "requirements don't matter" attitude; but not all requirements matter all the time to all people.

I'd like to add, though, this: you can't be safe in ignorance in Common Lisp. Things you don't know can hurt you. Less than in some other languages, but they are there. You probably won't be hurt by not knowing all the possibilities for combining docstrings and declares. But if you're ignorant of some things, you may get burned. Undefined behavior situations like modifying literal tree structure, or writing a program that parses untrusted Lisp data, not knowing about the #. syntax and * read-eval* . I'm not advocating unsafe ignorance. Not knowing the full flexibility of some syntax is generally safe, though.

> Explain this:

Which aspect of that error scenario isn't self-explanatory; what is left to explain?

From that one error, the listener has just taught us several important facts about the syntax which it accepts (which may be a superset of ANSI CL for all we know). It shows us that it accepts a docstring after a declare just fine, but that there must be at most one docstring. (At least, when the two are in that order, if we are to be strict in our guessing.)

So without looking at a shred of documentation outside of that error message, I'm already better informed.

The interactive nature of Lisp teaches! (Especially if the implementation is tight on error checking and has good diagnostics.)

What's left unsettled from that error situation is whether or not there may be multiple declares, since that case isn't being probed.


> Yes, it rather confirms that you can go far in Lisp without memorizing stuff like this!!!

That you don't know the relatively trivial syntax of DEFUN, shows that it is already non-obvious and you have to look it up.

You have failed to explain the syntax of DEFUN and you can't distinguish valid from invalid forms. I would never trust a code review done by you.

> You can bet your ass that if I had to implement an ANSI-CL conforming defun/lambda I'd get it right, of course.

Maybe. Maybe not.

> Which aspect of that error scenario isn't self-explanatory; what is left to explain?

Is that valid or not, given the syntax of Common Lisp? Does SBCL implement the syntax correctly or does it reject valid programs?

The syntax of DEFUN is:

    defun function-name lambda-list
      [[declaration* | documentation]]
      form*
Which says: any number of declarations and at most one documentation, in any order.

    (defun foo (a b)
      (declare (fixnum a))    ; declaration
      "foo"                   ; documentation
      "bar"                   ; form
      (+ a b))
Which indicates that SBCL rejects a valid program. I would not trust you to get it right as an implementor, given that you haven't even tried to verify it and that you are ignorant to Lisp syntax. I would not trust my own implementation without trying to come up with an extensive syntax test suite.

Similar:

    (defun foo () "a")           ; sbcl valid
    (defun foo () "a" "b")       ; sbcl valid
    (defun foo () "a" "b" "c")   ; sbcl rejects


Hi lispm. I investigated this more deeply and I'm afraid I cannot conclude that SBCL is wrong.

The root of the problem is this splicing [[ ]] extended BNF notational concoction, in whose description we find this:

... For example, the expression

  (x [[A | B* | C]] y)
means that at most one A, any number of B's, and at most one C can occur in any order. It is a description of any of these:

  (x y)
  (x B A C y)
  (x A B B B B B C y)
  (x C B A B B B y)
but not any of these:

  (x B B A A C C y)
  (x C B C y)
In the first case, both A and C appear too often, and in the second case C appears too often.

In the case of defun, we can identify C with documentation and y with forms. But documentation is a kind of form. According to the above, if we are given documentation documentation form, it doesn't match: documentation appears "too often". That appears to rule out "foo" "bar" as ill-formed, if "bar" is interpreted as documentation rather than form.

This is woefully badly specified; it is not clear how to unambiguously determine the extent of the symbols matched by a given [[ ]] notation.

There needs to be a clearly stated requirement that [[ ]], independently of what follows it, denotes (say) the longest possible sequence of symbols which is consistent with its constraints. The material which follows [[ ]] must then match against the remaining symbols in the form. Then it will be clear that given "foo" "bar", the "bar" string isn't part of the [[ declare(star) | documentation ]] spec, because the longest match ends with "foo" (if no declares follow).

Maybe it does. I'm afraid I cannot make head or tail out of the sentence "such that if n /=m and 1<=n,m<=j, then either Oin/=Oim or Oin = Oim = Qk, where for some 1<=k <=n, Ok is of the form Qk {star} . Furthermore, for each Oin that is of the form {Qk}1 , that element is required to appear somewhere in the list to be spliced. " Perhaps that rescues it somehow.


> I would never trust a code review done by you.

Why not? A code review has topics. It could be to enforce a coding convention.

Firstly, I would not pass code that uses multiple docstrings or a funny order for docstrings and declares or multiple declares; a coding convention should forbid such pointless shenanigans, whether or not they are ANSI conforming.

If the topic of the review was to determine whether the code is ANSI CL conforming, then I wouldn't just feed it to the listener of SBCL or any other implementation. Obviously, implementations can be nonconforming. They can accept, without diagnostic, inputs that require a diagnostic, as well as inputs that are nonportable or entirely undefined.

You can't determine conformance of the code, or of the implementation, or both, without reading and interpreting the applicable standard, obviously. (You didn't have to labor this far if you just wanted me to say that.)

> Does SBCL implement the syntax correctly or does it reject valid programs?

Even if we determine that SBCL is rejecting valid programs, that version of SBCL will forever continue to do so. We have to change to a working construct to get the code working.

Once we do that, the status of the nonworking construct that we replaced with a working one is rather moot. We have found all instances of that construct and replaced it, after which it no longer occurs in our code.

We may submit a bug report against SBCL. Since we fixed the code not to interact with the bug/noncompliance, we don't care when, if ever, SBCL issues a fix.

The nonworking construct could have been avoided in the first place by sticking to the simplified "canonical" syntax:

  (defun args [ docstring ] [ (declare ...) ] {form}*)
You can program defun-s for the rest of your Lisp programming life this way and never know the full syntax. You're also vanishingly unlikely to run into an implementation which doesn't accept the variations on this canonical syntax.

Deviations from this form can be rewritten into this form.

The exception might be machine-generated deviations. Like multiple declares or docstrings that are piled on by some macrology: if you want their output to be canonicalized, you have to insert some processing pass to do that normalization. That is annoying, and so we will feel better if we can blame it on a nonconformance in the implementation, even if we still have to do this work.

> (defun foo () "a" "b" "c") ; sbcl rejects

That's somewhat nasty; yet, there is no reason to write this kind of defun by hand. "a" is obviously a docstring, and "c" the return value. But "b" is superfluous in the sense that it has no effect.

If "b" contains documentation, it should be merged into "a" to produce the canonical form (defun foo () "ab" "c"): "ab" is the doc, "c" the returned object. If that doesn't work, then I care; that is uproarious.

I might be interested in knowing whether the above "a" "b" "c" is in fact invalid ANSI CL, if I'm more invested in that rejected form; like I have some macrology that produces it (so fixing the situation requires more work than just hunting down a couple of bad defuns). That macrology could be reused in other projects and so on.

Still, the fact that SBCL rejects it means that I can't have it if we are targetting SBCL. A workaround for SBCL (if that's what it is) might as well be applied all across the board.

So is it ANSI CL or not? The syntax is:

  defun function-name lambda-list [[declaration* | documentation]] form*
This [[]] notation is a special "splicing" extension of the BNF syntax which here indicates that there may be at most one docstring and any number of declarations, and these may appear in any order (so that a docstring can come between declares).


> 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))))))




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: