From: ··········@gmail.com
Subject: arg-shuffle-if pattern
Date: 
Message-ID: <0493c702-1c5c-479a-ad25-04e4a4e44944@f52g2000hsa.googlegroups.com>
In the function list-agree below, I have to repeat the call to scalar-
expand with the arguments in different order based on the result of
(scalarp n0)

I am leery of code where I nearly repeat myself. And must ask is there
some means of abstraction.

(defun scalar-expand (s lis)
  "SCALAR s -> LIST lis -> LIST s"
  (make-list (length lis) :initial-element s))

(defun list-agree (n0 n1)
  "LIST n0 -> LIST n1 -> LIST n0, n1"
  (if (scalarp n0)
      (scalar-expand n0 n1)
      (scalar-expand n1 n0)))

From: Tobias C. Rittweiler
Subject: Re: arg-shuffle-if pattern
Date: 
Message-ID: <87sl1pvgct.fsf@freebits.de>
···········@gmail.com" <··········@gmail.com> writes:

> In the function list-agree below, I have to repeat the call to scalar-
> expand with the arguments in different order based on the result of
> (scalarp n0)
>
> I am leery of code where I nearly repeat myself. And must ask is there
> some means of abstraction.
>
> (defun scalar-expand (s lis)
>   "SCALAR s -> LIST lis -> LIST s"
>   (make-list (length lis) :initial-element s))
>
> (defun list-agree (n0 n1)
>   "LIST n0 -> LIST n1 -> LIST n0, n1"
>   (if (scalarp n0)
>       (scalar-expand n0 n1)
>       (scalar-expand n1 n0)))

(funcall (ncall (mod (length (string (scalarp n0))) 3) #'flip #'scalar-expand)
         n1 n0)

where NCALL and FLIP can be found in my post scriptum.

Of course, the point of my posting is that readability is a tradeoff
between abstractness and concreteness, and that your original definition
was perfectly good enough from an abstraction point of view (there are
other things to mock about, though. You really should take a pill
against creeping schemetism.)

  -T.


P.S.


(defun ncall (n f arg)
  (check-type n number) (check-type f function)
  (if (<= n 0) 
      arg				; identity function
      (ncall (1- n) f (funcall f arg))))

(defun flip (f)
  #'(lambda (a b) (funcall f b a)))
From: Alex Mizrahi
Subject: Re: arg-shuffle-if pattern
Date: 
Message-ID: <4772973f$0$90275$14726298@news.sunsite.dk>
 mjc> In the function list-agree below, I have to repeat the call to scalar-
 mjc> expand with the arguments in different order based on the result of
 mjc> (scalarp n0)

is this pattern frequent enough? if it's not, it's not worth complicating 
matter because what you have now is perfectly readable and maintanable code.
(read Richard Gabriel's "Pattersn of Software" for a detailed explanations).

 mjc> I am leery of code where I nearly repeat myself. And must ask is there
 mjc> some means of abstraction.

that's quite easy to make arg-shuffle-if macro:

(defmacro arg-shuffle-if (condition (fun arg1 arg2))
  `(if ,condition (,fun ,arg1 ,arg2) (,fun ,arg2 ,arg1)))

if you want to do it w/o defining macros, i'm afraid it's not doable, 
because code is already quite compact, and it's not possible to make it more 
compact.

 mjc> (defun list-agree (n0 n1)
 mjc>   "LIST n0 -> LIST n1 -> LIST n0, n1"
 mjc>   (if (scalarp n0)
 mjc>       (scalar-expand n0 n1)
 mjc>       (scalar-expand n1 n0)))

(arg-shuffle-if (scalarp n0) (scalar-expand n0 n1))

however from this sample it seems you need not a arg-shuffle, but binding 
function parameters using their type but not actual position.
something like:

(defun-w/argtypes list-agree ((scalar atom) (list list))
    (scalar-expand scalar list))

writing defun-w/argtypes macro is left as an excersize to the reader :).

if you use classes as types, it's possible to reduce it to some

(defmethod-shuffle list-agree (scalar (list cons)) (scalar-expand scalar 
list))

which will generate two methods:

(defmethod list-agree (scalar (list cons)) (scalar-expand scalar list))
(defmethod list-agree ((list cons) scalar) (scalar-expand scalar list))

that's pretty easy 
From: Alan Crowe
Subject: Re: arg-shuffle-if pattern
Date: 
Message-ID: <86r6h5s3lr.fsf@cawtech.freeserve.co.uk>
···········@gmail.com" <··········@gmail.com> writes:

> In the function list-agree below, I have to repeat the call to scalar-
> expand with the arguments in different order based on the result of
> (scalarp n0)
> 
> I am leery of code where I nearly repeat myself. And must ask is there
> some means of abstraction.
> 
> (defun scalar-expand (s lis)
>   "SCALAR s -> LIST lis -> LIST s"
>   (make-list (length lis) :initial-element s))
> 
> (defun list-agree (n0 n1)
>   "LIST n0 -> LIST n1 -> LIST n0, n1"
>   (if (scalarp n0)
>       (scalar-expand n0 n1)
>       (scalar-expand n1 n0)))

(defun list-agree (n0 n1)
  "untested"
  (unless (scalarp n0)
    ;; canonicalise argument order
    (rotatef n0 n1))
  (scalar-expand n0 n1))

Alan Crowe
Edinburgh
Scotland