This is a read-only archive of lispforum.com. The forum was locked to new users and posts and is preserved here as static HTML from a database snapshot taken on 2019-09-07.

Favorite "underrated" Lisp feature?

14 posts · 13692 views

What's your favorite "underrated" Lisp feature?

For me, it's special variables. Those things reeeally save me from messy situations. Setting up contexts, so I don't have to change much code.

Though funnily enough, I've seen someone abuse the hell out of them. For instance, there'd be code like this:
(defun a_STZ ()
  (declare (special a stz verb i ...))
  (setf a 10)
  (b_STZ))

(defun b_STZ ()
  (declare (special a stz verb i ...))
  (list a))

(a_stz)
Now, I stripped the code to essentials here; the real code had all sorts of off-by-one errors. I still wonder how he (apparently) learned about DECLARE SPECIAL before LET -- it's like he'd manually add new variables to all the DECLARE SPECIAL declarations whenever he'd need a new one.

Until that point, /I/ didn't really know what DECLARE SPECIAL really did, and I had more Lisp experience than that programmer.

Re: Favorite "underrated" Lisp feature?

For me, it's probably generic functions. Before I "got it" I used to think of GFs simply as methods ala most other object models (C++, Java, etc.), only using a functional syntax, not a typical "message-based" syntax. That's only scratching the surface of what they can do, however. When you realize that GFs can be declared and used even if you never define a single CLOS object in your program and that you can use arbitrary symbols to do dispatching, you have a very powerful tool at your disposal. In fact, you have a generic dispatch mechanism that can all-but eliminate many boring dispatch tables in your code.

An that's without mixing in all the CLOS stuff, method combinations, wild MOP capabilities, etc. In short, very underrated. 8-)
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/

Re: Favorite "underrated" Lisp feature?

I like how you can easily transform code or add new code because syntax and 'everything returns value' concept does not stand on your way. This is very usefuly to me.

Re: Favorite "underrated" Lisp feature?

(FORMAT NIL "~r" some-integer) because it was the first time I've seen some of those words.

ED would be really cool if more implementations provided a resident editor.

Re: Favorite "underrated" Lisp feature?

I don't know about a "favorite" feature, but one underrated Common Lisp feature I appreciate is its pathnames support. Yes, some of it is too complicated, under-specified, or plain historical baggage, but in languages that don't support pathnames, the typical approach to dealing with them is to just use strings. I find that irksome: pathnames are structured objects, not mere character aggregates. I find that for casual, non-super-portable use the pathnames facility is both sufficient and pleasant.

P.S. regarding ED: I have this in my .swank.lisp:
#+sbcl
(push #'swank:ed-in-emacs sb-ext:*ed-functions*)

Re: Favorite "underrated" Lisp feature?

schoppenhauer wrote:Compiler Macros
Interesting. Care to say why? I have never really had an occasion to use a compiler macro. Regular macros, yes, all the time. Compiler macros, never.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/

Re: Favorite "underrated" Lisp feature?

tayssir wrote:I still wonder how he (apparently) learned about DECLARE SPECIAL before LET -- it's like he'd manually add new variables to all the DECLARE SPECIAL declarations whenever he'd need a new one.
Maybe he was reading through the CLHS index and DECLARE comes before LET? ;)

Re: Favorite "underrated" Lisp feature?

findinglisp wrote:
schoppenhauer wrote:Compiler Macros
Interesting. Care to say why? I have never really had an occasion to use a compiler macro. Regular macros, yes, all the time. Compiler macros, never.
Compiler macros are one of those things that you don't appreciate until you need them. That's why they are my favourite underrated feature as well. :)

The situation where I ended up using them involved trying to do code transformations on existing code that I did not have control over. By adding compiler macros on certain symbols, I could affect the code without changing any definitions in the code (assuming there were no existing compiler macros hanging around). This allowed me to write "code that observed code" very easily.

That sort of thing isn't something you need every day, but when you need it, it makes your job much simpler.

Re: Favorite "underrated" Lisp feature?

Yeah, you can often MacGyver a rabbit out of your hat with things like generic functions. For instance, someone mentioned the superiority of Haskell's notation for splitting definitions up:
    fib 0 = 0
    fib 1 = 1
    fib n = fib (n-1) + fib (n-2)
To be cute, I responded with:
(defmethod fib ((n (eql 0)))
  0)
(defmethod fib ((n (eql 1)))
  1)
(defmethod fib (n)
  (+ (fib (- n 1))
     (fib (- n 2))))
(Is this a silly trick? Well, maybe the whole example is silly -- people who actually need the Fibonacci numbers probably use a different algorithm, beyond even caching. ;) )

Or for those who really like single-inheritance, you can use the MOP and have single inheritance for yourself and your friends.

(Hmm, with single inheritance, I must sound like some people explaining their views on homosexuality: "I don't mind what people do, just as long as they don't force me to do it too.")

Re: Favorite "underrated" Lisp feature?

tayssir wrote: To be cute, I responded with:
(defmethod fib ((n (eql 0)))
  0)
(defmethod fib ((n (eql 1)))
  1)
(defmethod fib (n)
  (+ (fib (- n 1))
     (fib (- n 2))))
(Is this a silly trick? Well, maybe the whole example is silly -- people who actually need the Fibonacci numbers probably use a different algorithm, beyond even caching. ;) )
IMO, that specific case is a bit of a silly trick. In other words, I wouldn't write FIB that way, even if I used that simple algorithm, mostly because you have to have all the three pieces of it to work correctly and so if they all have to be defined together, you might as well put them in a single definition with a COND form. But, the silly trick does make the point quite well. 8-)

Where I find that the GF dispatch really helpful is where I want to effectively expand a dispatch table at runtime. Say you're writing a network analyzer that decodes packets. If you want to be able to have a modular system, where you can load new functions that decode different packet types, you'd like to avoid having all the logic that figures out the packet type and then hands the packet to the decode centralized. If you do that, you either end up editing the dispatch function every time you add a new decoder, or you end up designing a dynamic dispatching scheme using something like a hash table. That last one works, and is relatively easy to do, but it's so much easier to just define a generic function and have CLOS figure it all out. And optimize it all for high performance, for that matter.

Peter Seibel used this technique to great effect in his binary decoder routines in Practical Common Lisp. I was reading through those chapters when I had that "aha!" moment.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/

Re: Favorite "underrated" Lisp feature?

findinglisp wrote:
schoppenhauer wrote:Compiler Macros
Interesting. Care to say why? I have never really had an occasion to use a compiler macro. Regular macros, yes, all the time. Compiler macros, never.
As Geoff Wozniak already said, compiler macros are a good thing when needed. I actually never needed them until a few days ago (and I didnt even write the first I used myself - the situation where I needed them is complicated, dont want to explain that now). I thought, "underrated" means something like "not widely used", "not often on topic". And thats what I think compiler macros are.

I think compiler macros are something, other Languages could benefit from. Compilers for other Languages are using Heuristics for optimizing, they are replacing code that will always have a constant value by the value, "inlining" small functions that are not declared externally, removing unused variables (unless declared volatile, etc.), etc. - they do anything that can be done at the moment to "guess" whats best for optimizing your code, and so do all good CL-Compilers - I even read somewhere (dont know where) that somebody wants to attatch Artificial Intelligence to the GNU Compiler Collection for optimizing. But there will certainly always, or at least for a long time, be Situations where it isnt clear to the compiler, and where the Compiler cannot guess that some value is easier to calculate in special cases which are known before compiling, but which are not "obvious". And with compiler macros, you can tell the Compiler what to do, if it cannot know exactly itself. There may only be few situations where this is useful, but then it is a good feature.
Sorry for my bad english.
Visit my blog http://blog.uxul.de/

Re: Favorite "underrated" Lisp feature?

The compiler macro feature is definitely an advanced feature. I'm not even entirely sure I've ever written one myself. Here's an example. If I'm not mistaken, the idea here is to optimize out the need for the "if" at runtime, in a common case. It's not at all clear that this optimization is tremendously important, and the amount of programmer time needed to make quite sure that the define-compiler-macro form is bug-free may well be more than the total amount of speedup that this will ever provide anywhere.
(defun curry (function &rest args)

  "Return a function of any number of arguments, which, when
   called, calls the given function on the given args followed
   by all those arguments."

  (if (and args (null (cdr args)))      ;fast test for length = 1
    (let ((arg (car args)))
      #'(lambda (&rest more-args)
          (apply function arg more-args)))
    #'(lambda (&rest more-args)
	(apply function (append args more-args)))))

(define-compiler-macro curry (&whole form function &rest args &environment env)

  "Return a function of any number of arguments, which, when
   called, calls the given function on the given args followed
   by all those arguments."

  (declare (ignore env))
  (if (and (listp function)
	   (eq (first function) 'function)
	   (symbolp (second function))
	   (and args (null (cdr args))))
    `#'(lambda (&rest more-args)
	 (apply ,function ,(car args) more-args))
    form))

Re: Favorite "underrated" Lisp feature?

My favourite, ridiculously underappreciated feature of Common Lisp? Its community.