Page 1 of 2

Tree expression shortener; seperator

PostPosted: Sun Oct 12, 2008 11:37 pm
by Jasper
It could be possible to save a character per sublist: use a symbol as separator. I will use a seperator ';' and '|' as a blocker of separated sublisting. (Although they wouldnt work for common lisp since they are already used.)

If you read in the blocker and separator as symbols, you can make them work like this. (Feel like this code is rather clumsy though.)
Code: Select all
(defun apply-separators (tree separator blocker)
  (let  (here out sublist)
  (flet ((add-here ()
      (if sublist
          (push (reverse here) out)
          (setf out (append here out)))
      (setf sublist nil)
      (setf here nil)))
    (dolist (el tree)
     (cond
       ((eql el separator)
          (setf sublist t)
          (push (reverse here) out)
          (setf here nil))
      ((eql el blocker)
          (add-here))
      (t
         (push (if (listp el)
                     (apply-separators el separator blocker)el)
                   here))))
    (unless (null here)
      (add-here))
    (reverse out))))

This will convert stuff like this: (b-> '|', s-> ';')
Code: Select all
(apply-separators '(1 2 3 s (4 5 s 6 7 b 1 2) 4 6 s 4 9 1 b 1 2 3 4 5 b 1 4 s 5 5) 's 'b) -> ((1 2 3) ((4 5) (6 7) 1 2) (4 6) (4 9) 1 2 3 4 (1 4) (5 5))

This can make some code prettier, especially very non-functional code, and when you need sublists, here i also added xml-like stuff.
Code: Select all
<defmethod apply-separators> (tree list ; separator symbol ; blocker symbol)
  (let  (here out sublist)
  (flet ((add-here () |
            if sublist
               (push (reverse here) out)
               (setf out (append here out));
           setf sublist nil;
           setf here nil;))
    (dolist (el tree)
      (cond
        (eql el separator;
           setf sublist t;
           push (reverse here) out;
           setf here nil;)
        (eql el blocker;
           add-here;)
        (t
          push (if (listp el)
                        (apply-separators el separator blocker) el)
                  here;)))
    (unless | null here;
      add-here;)
    (reverse out)))
</defmethod apply-separators>

Now, i myself am not sure if this is a good idea. But what do you think? Could i get slime to accept it? (Edit: changed it to make it a little more readable.)
It does cut down on a look of hooks. Although newbies are often scared of hooks, it might be a good idea to let them use the hooks because if they don't, they might not realize properly(or as fast) that there are lists in there.

Re: Tree expression shortener; seperator

PostPosted: Mon Oct 13, 2008 1:39 am
by schoppenhauer
In your Example, it seems to me that you just replace '(' by 's' and ')' by 'b'. I dont see any advantage.

Re: Tree expression shortener; seperator

PostPosted: Mon Oct 13, 2008 3:25 am
by Jasper
You need to look better. Or count the hooks, 's and 'b 's. Note that s <-> ; and b <-> | its just that ; and | dont make good symbols. (Well, |;|) Or look at the code i changed with it. The lack of many hooks.

Re: Tree expression shortener; seperator

PostPosted: Mon Oct 13, 2008 10:23 am
by qbg
What it seems that you want here are reader macros. The possible problem then is that it might make the underlying tree harder to see.

Re: Tree expression shortener; seperator

PostPosted: Tue Oct 14, 2008 6:13 pm
by Jasper
@qbg: I agree with you there. But in a way, the changed code can look cleaner, although it is less clean for having more syntax. It saves n+1 characters for a list with only lists as elements.
The adding of syntax, and decreasing sight of the tree are the issues here afaik. I think it can make the code better when it used wisely with the following rules: (Didn't use newlines for space here as i would in code.)
In lets:
Code: Select all
(let (a 1; b 2; c 3) ..body..

In bodies:
Code: Select all
(progn | do-thing-one; do-thing-two 1 2; do-third-thing 'x;)

In arguments of methods:
Code: Select all
(defmethod power (a integer ; b number) ..body..)

Defstructs/defclass:
Code: Select all
(defclass cookie () ( maker :type person :initform 'spaghettimonster :accessor maker :initarg maker ; deliciousness :initform 'infinite ; :accessor deliciousness :initarg deliciousness ; )

Etcetera. One place i think this should not be used is in arguments of functions. Maybe a good rule should be that the place where it could be used is 'special', it shouldnt have sub-lists where you could also demand to use this system for. You cannot use the system in the sublists the separator makes, unless you use a second set of characters for the blocker and separator. The body-layer of functions are special, because its arguments are not body-layer. You can use the system in conjunction with the context in this way.
An issue here is macros where two try to 'claim' to be able to use this system, while in the same time be each other as direct arguments. An attempt of resolving it is to only do it when they do not conflict with earlier more basic ones, like the let,progn and defmethod here. (But this resolving might not be enough if they are unconnected/both satisfy.)

Re: Tree expression shortener; seperator

PostPosted: Tue Oct 14, 2008 6:41 pm
by findinglisp
Jasper wrote:Now, i myself am not sure if this is a good idea. But what do you think? Could i get slime to accept it? (Edit: changed it to make it a little more readable.)
It does cut down on a look of hooks. Although newbies are often scared of hooks, it might be a good idea to let them use the hooks because if they don't, they might not realize properly(or as fast) that there are lists in there.


I wouldn't use this syntax myself. My own philosophy is to "embrace the parentheses." (pardon the pun ;) )

I use paredit in Emacs a lot. I'm constantly moving code around using sexpr-level editing commands and I've come to love parens for that. IMO, saving a character here or there, particularly a character that paredit automatically inserts and deletes for me, is not really useful.

Re: Tree expression shortener; seperator

PostPosted: Tue Oct 14, 2008 7:02 pm
by sburson
findinglisp wrote:I wouldn't use this syntax myself. My own philosophy is to "embrace the parentheses." (pardon the pun ;) )

I use paredit in Emacs a lot. I'm constantly moving code around using sexpr-level editing commands and I've come to love parens for that. IMO, saving a character here or there, particularly a character that paredit automatically inserts and deletes for me, is not really useful.


It's really funny how everybody thinks the parentheses are a problem at first. You've probably heard the story, but I think it's worth repeating as many times as necessary: when McCarthy invented Lisp, he did not intend people to use the S-expression notation for programs. There was a more traditional notation called M-expressions. However, it didn't catch on; people actually liked the S-expression syntax. There was a reason for this, I'd suggest, even before we had packages like paredit. The uniformity of notation turns out to be very powerful and convenient.

As counterintuitive as it seems to newcomers, the parentheses are one of the best things about Lisp. There is plenty of evidence for this. Starting with McCarthy's M-expressions, there have been repeated attempts to introduce standard infix syntax to the Lisp world. Although most of these have been compatible, in the sense that they allowed the same code to be written in either syntax, none of them have caught on.

Do check out paredit. It is the Right Way to edit Lisp and makes the parentheses even less obtrusive and more powerful.

Re: Tree expression shortener; seperator

PostPosted: Tue Oct 14, 2008 9:57 pm
by qbg
findinglisp wrote:I use paredit in Emacs a lot. I'm constantly moving code around using sexpr-level editing commands and I've come to love parens for that. IMO, saving a character here or there, particularly a character that paredit automatically inserts and deletes for me, is not really useful.

(:rant "I don't know if I like paredit all that much; maybe I'm just not using it right (I don't do a lot of sexp-level editing commands). I also don't like it when paredit screws up the number of parentheses that there should be (and I find my self using C-q to insert one to fix it, or use #| |# (which is another thing it doesn't handle so well) to fix it, or just turn off paredit-mode).")

Re: Tree expression shortener; seperator

PostPosted: Tue Oct 14, 2008 10:54 pm
by Paul Donnelly
qbg wrote:
findinglisp wrote:I use paredit in Emacs a lot. I'm constantly moving code around using sexpr-level editing commands and I've come to love parens for that. IMO, saving a character here or there, particularly a character that paredit automatically inserts and deletes for me, is not really useful.

(:rant "I don't know if I like paredit all that much; maybe I'm just not using it right (I don't do a lot of sexp-level editing commands). I also don't like it when paredit screws up the number of parentheses that there should be (and I find my self using C-q to insert one to fix it, or use #| |# (which is another thing it doesn't handle so well) to fix it, or just turn off paredit-mode).")

I never "got" paredit either. I may give it another try though, since some people like it so much.

Re: Tree expression shortener; seperator

PostPosted: Wed Oct 15, 2008 9:00 am
by findinglisp
qbg wrote:
findinglisp wrote:I use paredit in Emacs a lot. I'm constantly moving code around using sexpr-level editing commands and I've come to love parens for that. IMO, saving a character here or there, particularly a character that paredit automatically inserts and deletes for me, is not really useful.

(:rant "I don't know if I like paredit all that much; maybe I'm just not using it right (I don't do a lot of sexp-level editing commands). I also don't like it when paredit screws up the number of parentheses that there should be (and I find my self using C-q to insert one to fix it, or use #| |# (which is another thing it doesn't handle so well) to fix it, or just turn off paredit-mode).")


I don't find that paredit screws up parentheses much. It does, admittedly, but not often. When it happens, it's slightly annoying, but not much.

You are correct, however, that it doesn't handle #| |# very well. I typically turn on transient-mark-mode and then use M-; to comment out large blocks of code.

I will admit that it took me a short while to get used to it, but now that I am, I'm hooked.