From: ········@hex.net
Subject: Re-raveling &REST idiom
Date: 
Message-ID: <Zhdc7.31579$5c.2254149@news20.bellglobal.com>
[Feel free to tell me I'm doing something dumb...  :-)]
<not-homework-query>

I've written some code that "wraps up" MH mailer commands, and find
myself in the state of thinking I'd like to have both:

(defun make-mh-command (COMMAND &rest ARGS)
  "Generate Unix commandline to invoke the MH command COMMAND, with ARGS"
  ...)

and

(defun run-mh-command (COMMAND &rest ARGS)
  (common-lisp-user::run-shell-command
     (make-mh-command COMMAND ???WHAT-do-I-do-with-ARGS???)))

It would be easy enough to duplicate the code in both places, but that
seems rather inelegant.  What I'd rather do is to have run-mh-command
invoke make-mh-command, passing in the arguments much as it received
them.

Simplest answer:
(defun run-mh-command (COMMAND &rest ARGS)
  (common-lisp-user::run-shell-command
     (make-mh-command COMMAND ARGS)))

> (run-mh-command "folder" "+inbox" "-pack")
results in COMMAND being bound to "folder", and ARGS being bound to
("+inbox" "-pack")

When I pass that on to make-mh-command, COMMAND will be OK, but ARGS
will be a nested list:
(("+inbox" "-pack"))

It's easy enough to have make-mh-command check to see if ARGS is a
list of lists, and go that way; is there some cleverness so that ARGS
can be unraveled into a set of arguments again?

[Feel free to accuse me of working too hard towards some artificial
and pointless notion of "elegance" that doesn't ultimately matter...]
</not-homework-query>
-- 
(concatenate 'string "cbbrowne" ·@acm.org")
http://vip.hex.net/~cbbrowne/
M$ is  for people  who want a  half-way implementation  of yesterday's
ideas tomorrow.

From: Kaz Kylheku
Subject: Re: Re-raveling &REST idiom
Date: 
Message-ID: <5udc7.31846$B37.659812@news1.rdc1.bc.home.com>
In article <······················@news20.bellglobal.com>,
········@hex.net wrote:
>I've written some code that "wraps up" MH mailer commands, and find
>myself in the state of thinking I'd like to have both:
>
>(defun make-mh-command (COMMAND &rest ARGS)
>  "Generate Unix commandline to invoke the MH command COMMAND, with ARGS"
>  ...)
>
>and
>
>(defun run-mh-command (COMMAND &rest ARGS)
>  (common-lisp-user::run-shell-command
>     (make-mh-command COMMAND ???WHAT-do-I-do-with-ARGS???)))

Are you by chance looking for

	(apply #'make-mh-command command args)

?
From: Ingvar Mattsson
Subject: Re: Re-raveling &REST idiom
Date: 
Message-ID: <87ae1ak06c.fsf@gruk.tech.ensign.ftech.net>
········@hex.net writes:

> [Feel free to tell me I'm doing something dumb...  :-)]
> <not-homework-query>
> 
> I've written some code that "wraps up" MH mailer commands, and find
> myself in the state of thinking I'd like to have both:
> 
> (defun make-mh-command (COMMAND &rest ARGS)
>   "Generate Unix commandline to invoke the MH command COMMAND, with ARGS"
>   ...)
> 
> and
> 
> (defun run-mh-command (COMMAND &rest ARGS)
>   (common-lisp-user::run-shell-command
>      (make-mh-command COMMAND ???WHAT-do-I-do-with-ARGS???)))

Does:
(defun run-mh-command (COMMAND &rest ARGS)
   (common-lisp-user::run-shell-command
      `(make-mh-command COMMAND ,@ARGS)))
work?

This probably has some gotchas I haven't thought about, so...

//Ingvar (see below code for gotchas I hadn't considered)
-- 
(defmacro fakelambda (args &body body) 
 `(lambda ,args (labels ((me ,args ,@body)) (me ,@args))))
(funcall (fakelambda (a b) (if (zerop (length a)) b (format nil "~a~a" 
 (aref a 0) (me b (subseq a 1))))) "Js nte iphce" "utaohrls akr")
From: Kaz Kylheku
Subject: Re: Re-raveling &REST idiom
Date: 
Message-ID: <b_dc7.32137$B37.661534@news1.rdc1.bc.home.com>
In article <··············@gruk.tech.ensign.ftech.net>, Ingvar Mattsson wrote:
>········@hex.net writes:
>> (defun run-mh-command (COMMAND &rest ARGS)
>>   (common-lisp-user::run-shell-command
>>      (make-mh-command COMMAND ???WHAT-do-I-do-with-ARGS???)))
>
>Does:
>(defun run-mh-command (COMMAND &rest ARGS)
>   (common-lisp-user::run-shell-command
>      `(make-mh-command COMMAND ,@ARGS)))
>work?

No, because it simply computes (and returns) the list

	(make-mh-command COMMAND ...)

which requires an eval.  So what you seem to want is:

(defun run-mh-command (COMMAND &rest ARGS)
   (common-lisp-user::run-shell-command
      (eval `(make-mh-command ,COMMAND ,@ARGS))))

Also note that you want ,COMMAND not COMMAND.  You want the *value* of
the COMMAND parameter to be the argument to make-hm-command, not the
COMMAND *symbol*, which eval won't be able to resolve to the proper
value, because the binding is not visible to eval.

But this is still wrong, because now the value of COMMAND will undergo
an extra level of evaluation. So for instance if COMMAND
has the value '(1 2), eval will try to call the function 1.

So what you need is

     (eval `(make-mh-command ',COMMAND ,@ARGS))

You want the value of COMMAND to be substituted into the list, but
quoted so that eval won't evaluate it again. Okay, that's great
but what about ARGS? That has the same problem. Each argument
is simply plugged into the form, and will undergo second evaluation.
You need each separate argument to be plugged into the form, but
quoted:

     (eval `(make-mh-command ',COMMAND 
	,@(mapcar #'(lambda (x) `(quote ,x)) ,ARGS)))	;; blech!

The use of quote has to be wrapped in a function or closure, because
quote is a special operator, and so we can't directly use it in mapcar.
That is, we can't do ,@(mapcar #'quote ,ARGS) nice as that would be.

So in the end, it's easier and cleaner to just use the

    (apply #'make-mh-command command args)

idiom.
From: Raymond Wiker
Subject: Re: Re-raveling &REST idiom
Date: 
Message-ID: <8666bybk9b.fsf@raw.grenland.fast.no>
········@hex.net writes:

> [Feel free to tell me I'm doing something dumb...  :-)]
> <not-homework-query>
> 
> I've written some code that "wraps up" MH mailer commands, and find
> myself in the state of thinking I'd like to have both:
> 
> (defun make-mh-command (COMMAND &rest ARGS)
>   "Generate Unix commandline to invoke the MH command COMMAND, with ARGS"
>   ...)
> 
> and
> 
> (defun run-mh-command (COMMAND &rest ARGS)
>   (common-lisp-user::run-shell-command
>      (make-mh-command COMMAND ???WHAT-do-I-do-with-ARGS???)))
> 
> It would be easy enough to duplicate the code in both places, but that
> seems rather inelegant.  What I'd rather do is to have run-mh-command
> invoke make-mh-command, passing in the arguments much as it received
> them.
> 
> Simplest answer:
> (defun run-mh-command (COMMAND &rest ARGS)
>   (common-lisp-user::run-shell-command        
>      (make-mh-command COMMAND ARGS)))
> 
> > (run-mh-command "folder" "+inbox" "-pack")
> results in COMMAND being bound to "folder", and ARGS being bound to
> ("+inbox" "-pack")
> 
> When I pass that on to make-mh-command, COMMAND will be OK, but ARGS
> will be a nested list:
> (("+inbox" "-pack"))

How about using 

        (apply #'make-mh-command COMMAND ARGS)

instead?

        That should take care of the double nesting, I think...

        E.g:

(defun make-mh-command (COMMAND &rest ARGS)
  (cons COMMAND (copy-seq ARGS)))

(defun run-mh-command (command &rest args)
  (format t "~%~a~%" (apply #'make-mh-command command args)))

-- 
Raymond Wiker
·············@fast.no
From: Nils Goesche
Subject: Re: Re-raveling &REST idiom
Date: 
Message-ID: <lklmku1nug.fsf@pc022.bln.elmeg.de>
········@hex.net writes:

> I've written some code that "wraps up" MH mailer commands, and find
> myself in the state of thinking I'd like to have both:
> 
> (defun make-mh-command (COMMAND &rest ARGS)
>   "Generate Unix commandline to invoke the MH command COMMAND, with ARGS"
>   ...)
> 
> and
> 
> (defun run-mh-command (COMMAND &rest ARGS)
>   (common-lisp-user::run-shell-command
>      (make-mh-command COMMAND ???WHAT-do-I-do-with-ARGS???)))
> 
> It would be easy enough to duplicate the code in both places, but that
> seems rather inelegant.  What I'd rather do is to have run-mh-command
> invoke make-mh-command, passing in the arguments much as it received
> them.
> 
> Simplest answer:
> (defun run-mh-command (COMMAND &rest ARGS)
>   (common-lisp-user::run-shell-command
>      (make-mh-command COMMAND ARGS)))

[snip]

I think you want

(defun run-mh-command (COMMAND &rest ARGS)
   (common-lisp-user::run-shell-command
      (apply #'make-mh-command COMMAND ARGS)))
-- 
Nils Goesche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x42B32FC9
From: Reini Urban
Subject: Re: Re-raveling &REST idiom
Date: 
Message-ID: <9ktgmn$jr$3@fstgss02.tu-graz.ac.at>
Nils Goesche <······@cartan.de> wrote:
: ········@hex.net writes:
: (defun run-mh-command (COMMAND &rest ARGS)
:    (common-lisp-user::run-shell-command
:       (apply #'make-mh-command COMMAND ARGS)))

BTW: This (&rest => apply) is one of the candidates for a typical lisp 
software pattern, e.g. for CLiki or Ward's Wiki.

someone has to come up with a precise pattern formulation for this 
to help newbies.
-- 
Reini Urban
http://xarch.tu-graz.ac.at/acadwiki/AutoLispFaq