From: Brad Settlemyer
Subject: Easy question (elisp)
Date: 
Message-ID: <YwkC8.48923$YQ1.21637592@typhoon.southeast.rr.com>
Hello,

  I am a relative lisp novice, but in the course of doing a few things with 
XEmacs, I've encountered a lisp hitch I want to understand better (I've 
asked on an xemacs group to no avail).

  Specifically, consider the following function:

  (custom-set-faces &rest ARGS)

  This function apparently takes discrete arguments, rather than a list of 
arguments (if anyone wants to explain the rationale, that would be fine 
also as each parameter is the same thing, a spec entry).

  I have a case where I have multiple lists of spec entries defined like 
this:

(defconst dark-bg-faces
  '( '(font-lock-comment-face ((t (:foreground "pink"))) t)
     '(font-lock-constant-face ((t (:foreground "cyan"))) t)))

(defconst light-bg-faces
  '( '(font-lock-comment-face ((t (:foreground "firebrick"))) t)
     '(font-lock-constant-face ((t (:foreground "ForestGreen"))) t)))

And I would like to do something like this

(custom-set-faces 'light-bg-faces)

Which obviously doesn't work, as custom set faces is supposed to take spec 
entries, rather than a list of spec entries.  I have several ways to work 
around this problem, but it seems to me that there may be a really neat way 
of binding each element in the list to unnamed variables using a let 
expression, and that may be a very elegant solution to some of the ways I 
sometimes change the font entries interactively (rather than having to use 
a iterative expression).  Is this possible and simple, or impossible/messy?

Thanks for any help,
-- 
Brad Settlemyer
http://deepcopy.org/
Progamming in the trenches

From: Brad Settlemyer
Subject: Re: Easy question (elisp)
Date: 
Message-ID: <vQkC8.48988$YQ1.21672175@typhoon.southeast.rr.com>
Brad Settlemyer wrote:

>   Specifically, consider the following function:
> 
>   (custom-set-faces &rest ARGS)
> 
>   This function apparently takes discrete arguments, rather than a list of
> arguments (if anyone wants to explain the rationale, that would be fine
> also as each parameter is the same thing, a spec entry).
> 
>   I have a case where I have multiple lists of spec entries defined like
> this:
> 
> (defconst dark-bg-faces
>   '( '(font-lock-comment-face ((t (:foreground "pink"))) t)
>      '(font-lock-constant-face ((t (:foreground "cyan"))) t)))
> 
> (defconst light-bg-faces
>   '( '(font-lock-comment-face ((t (:foreground "firebrick"))) t)
>      '(font-lock-constant-face ((t (:foreground "ForestGreen"))) t)))
> 
> And I would like to do something like this
> 
> (custom-set-faces 'light-bg-faces)
> 

Hmm, I was just catching up on the traffic on the newsgroup, and it appears 
that values-list may be the answer, but thus far I haven't been able to get 
it to work.  Hopefully this question isn't overly redundant, I know that 
there are several groups I don't read because of the incessant newby 
repetitiveness.  Again, thanks for any help.
-- 
Brad Settlemyer
http://deepcopy.org/
Progamming in the trenches
From: Brad Settlemyer
Subject: Re: Easy question (elisp)
Date: 
Message-ID: <x3mC8.53821$gd5.22076525@typhoon.southeast.rr.com>
Brad Settlemyer wrote:

> Hello,
> 
>   I am a relative lisp novice, but in the course of doing a few things
>   with
> XEmacs, I've encountered a lisp hitch I want to understand better (I've
> asked on an xemacs group to no avail).
> 
>   Specifically, consider the following function:
> 
>   (custom-set-faces &rest ARGS)
> 

I've gotten the answer.  ELisp doesn't support the common lisp impl of 
values-list (grrr), I had to emulate the functionality using 
multiple-value-bind, which isn't quite as neat, but does work.  Sorry to 
interupt your regularly scheduled entertainment, I had a misplaced quote in 
my defined lists that was screwing me up.
-- 
Brad Settlemyer
http://deepcopy.org/
Progamming in the trenches
From: Ingvar Mattsson
Subject: Re: Easy question (elisp)
Date: 
Message-ID: <87wuudrcyg.fsf@gruk.tech.ensign.ftech.net>
Brad Settlemyer <···········@deepcopy.org> writes:

> Brad Settlemyer wrote:
> 
> > Hello,
> > 
> >   I am a relative lisp novice, but in the course of doing a few things
> >   with
> > XEmacs, I've encountered a lisp hitch I want to understand better (I've
> > asked on an xemacs group to no avail).
> > 
> >   Specifically, consider the following function:
> > 
> >   (custom-set-faces &rest ARGS)
> > 
> 
> I've gotten the answer.  ELisp doesn't support the common lisp impl of 
> values-list (grrr), I had to emulate the functionality using 
> multiple-value-bind, which isn't quite as neat, but does work.  Sorry to 
> interupt your regularly scheduled entertainment, I had a misplaced quote in 
> my defined lists that was screwing me up.

Hmm, I guess using apply would be even prettier.

(let ((faces-list (list ...)))
  (apply #'custom-set-faces faces-list))

Utterly untried and so forth, but...

//Ingvar
-- 
When in doubt, debug-on-entry the function you least suspect have
anything to do with something.
From: Kalle Olavi Niemitalo
Subject: Re: Easy question (elisp)
Date: 
Message-ID: <87bsbphguq.fsf@Astalo.y2000.kon.iki.fi>
Brad Settlemyer <···········@deepcopy.org> writes:

> (defconst dark-bg-faces
>   '( '(font-lock-comment-face ((t (:foreground "pink"))) t)
>      '(font-lock-constant-face ((t (:foreground "cyan"))) t)))
> 
> (defconst light-bg-faces
>   '( '(font-lock-comment-face ((t (:foreground "firebrick"))) t)
>      '(font-lock-constant-face ((t (:foreground "ForestGreen"))) t)))
> 
> And I would like to do something like this
> 
> (custom-set-faces 'light-bg-faces)

I'll give you a few solutions.


1. You could do it like this:

  (eval (cons 'custom-set-faces light-bg-faces))
or
  (eval `(custom-set-faces ,@light-bg-faces))

These first compute the list

  (custom-set-faces
   '(font-lock-comment-face ((t (:foreground "firebrick"))) t)
   '(font-lock-constant-face ((t (:foreground "ForestGreen"))) t))

and then evaluate it with the eval function.


2. If you remove the inner quotes, like this:

  (defconst light-bg-faces
    '((font-lock-comment-face ((t (:foreground "firebrick"))) t)
      (font-lock-constant-face ((t (:foreground "ForestGreen"))) t)))

then you can apply the custom-set-faces function to this list of
arguments.

  (apply 'custom-set-faces light-bg-faces)
or
  (apply #'custom-set-faces light-bg-faces)

In Emacs Lisp, there is no difference between these; but in
Common Lisp, only #' can refer to local functions defined with
FLET or LABELS.


3. You seem to be defining separate sets of face specifications
for dark and light backgrounds, then presumably choosing one set
at runtime.  You could instead handle both dark and light
backgrounds in the same specifications:

  (custom-set-faces
   '(font-lock-comment-face ((((background dark))
                              (:foreground "pink"))
                             (((background light))
                              (:foreground "firebrick"))) t)
   '(font-lock-constant-face ((((background dark))
                              (:foreground "cyan"))
                             (((background light))
                              (:foreground "ForestGreen"))) t))

This has the advantage that you can keep editing the faces with
customize-face.


4.
> there may be a really neat way of binding each element in the
> list to unnamed variables using a let expression

You can't have unnamed variables.  Gensyms are the closest you
can get.  You would have to construct the let expression at
runtime and then evaluate it with eval.

  (eval
   (let* ((bindings (mapcar #'(lambda (spec)
                                (list (gensym) spec))
                            light-bg-faces))
          (gensyms (mapcar #'car bindings)))
     `(let ,bindings
        (custom-set-faces ,@gensyms))))

See my solution 1 for a simpler way of using eval.