[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.lisp

Passing variable keywords to another function

Mart van de Wege

7/18/2015 10:51:00 AM

Hi all,

I'm trying to build a constructor function that calls make-instance, but
the number of arguments to pass to make-instance is unknown and depends
on the number of parameters passed to the original function.

I can do this with a macro easily, but is it possible to do it with a
function?

If I try this:

(defclass testclass ()
((first-slot :initarg :first-slot)
(second-slot :initarg :second-slot)))

(defun make-test-class (&rest args)
(make-instance 'testclass args))

then (make-test-class :first-slot 1) will fail because it
passes args as a single list to make-instance; I need a way to easily
destructure a list with an unknown number of elements to pass it to
make-instance. The ,@ operator does this in a macro; how can I do the
same in a function?

Mart

--
"We will need a longer wall when the revolution comes."
--- AJS, quoting an uncertain source.
14 Answers

Pascal J. Bourguignon

7/18/2015 11:13:00 AM

0

Mart van de Wege <mvdwege@gmail.com> writes:

> Hi all,
>
> I'm trying to build a constructor function that calls make-instance, but
> the number of arguments to pass to make-instance is unknown and depends
> on the number of parameters passed to the original function.
>
> I can do this with a macro easily, but is it possible to do it with a
> function?
>
> If I try this:
>
> (defclass testclass ()
> ((first-slot :initarg :first-slot)
> (second-slot :initarg :second-slot)))
>
> (defun make-test-class (&rest args)
> (make-instance 'testclass args))

(defun make-test-class (&rest args &key)
(apply (function make-instance) 'testclass :allow-other-keys t args))


--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

Dimitri Fontaine

7/18/2015 11:15:00 AM

0

Mart van de Wege <mvdwege@gmail.com> writes:
> (defclass testclass ()
> ((first-slot :initarg :first-slot)
> (second-slot :initarg :second-slot)))
>
> (defun make-test-class (&rest args)
> (make-instance 'testclass args))

I think you want:

(defun make-test-class (&rest args)
(apply #' make-instance 'testclass args))

--
dim

Pascal Costanza

7/18/2015 11:30:00 AM

0

On 18/07/2015 12:50, Mart van de Wege wrote:
> Hi all,
>
> I'm trying to build a constructor function that calls make-instance, but
> the number of arguments to pass to make-instance is unknown and depends
> on the number of parameters passed to the original function.
>
> I can do this with a macro easily, but is it possible to do it with a
> function?
>
> If I try this:
>
> (defclass testclass ()
> ((first-slot :initarg :first-slot)
> (second-slot :initarg :second-slot)))
>
> (defun make-test-class (&rest args)
> (make-instance 'testclass args))

(defun make-test-class (&rest args)
(apply #'make-instance 'testclass args))

Also:

(defun make-test-class (&rest args &key first-slot second-slot)
(apply #'make-instance 'testclass
:first-slot (modify-value first-slot)
args))

etc.

Pascal

--
My website: http:/...
Common Lisp Document Repository: http://cdr.eu...
Closer to MOP & ContextL: http://common-lisp.net/proje...
The views expressed are my own, and not those of my employer.

gengyangcai

7/18/2015 12:23:00 PM

0

On Saturday, July 18, 2015 at 6:56:07 PM UTC+8, Mart van de Wege wrote:
> Hi all,
>
> I'm trying to build a constructor function that calls make-instance, but
> the number of arguments to pass to make-instance is unknown and depends
> on the number of parameters passed to the original function.
>
> I can do this with a macro easily, but is it possible to do it with a
> function?
>
> If I try this:
>
> (defclass testclass ()
> ((first-slot :initarg :first-slot)
> (second-slot :initarg :second-slot)))
>
> (defun make-test-class (&rest args)
> (make-instance 'testclass args))
>
> then (make-test-class :first-slot 1) will fail because it
> passes args as a single list to make-instance; I need a way to easily
> destructure a list with an unknown number of elements to pass it to
> make-instance. The ,@ operator does this in a macro; how can I do the
> same in a function?
>
> Mart
>
> --
> "We will need a longer wall when the revolution comes."
> --- AJS, quoting an uncertain source.

This is what I got when I ran your code :

CL-USER 1 > (defclass testclass ()
((first-slot :initarg :first-slot)
(second-slot :initarg :second-slot)))
#<STANDARD-CLASS TESTCLASS 2009FAA3>

CL-USER 2 >
(defun make-test-class (&rest args)
(make-instance 'testclass args))
MAKE-TEST-CLASS

Pascal J. Bourguignon

7/18/2015 12:24:00 PM

0

CAI GENGYANG <gengyangcai@gmail.com> writes:

> On Saturday, July 18, 2015 at 6:56:07 PM UTC+8, Mart van de Wege wrote:
>> Hi all,
>>
>> I'm trying to build a constructor function that calls make-instance, but
>> the number of arguments to pass to make-instance is unknown and depends
>> on the number of parameters passed to the original function.
>>
>> I can do this with a macro easily, but is it possible to do it with a
>> function?
>>
>> If I try this:
>>
>> (defclass testclass ()
>> ((first-slot :initarg :first-slot)
>> (second-slot :initarg :second-slot)))
>>
>> (defun make-test-class (&rest args)
>> (make-instance 'testclass args))
>>
>> then (make-test-class :first-slot 1) will fail because it
>> passes args as a single list to make-instance; I need a way to easily
>> destructure a list with an unknown number of elements to pass it to
>> make-instance. The ,@ operator does this in a macro; how can I do the
>> same in a function?
>>
>> Mart
>>
>> --
>> "We will need a longer wall when the revolution comes."
>> --- AJS, quoting an uncertain source.
>
> This is what I got when I ran your code :
>
> CL-USER 1 > (defclass testclass ()
> ((first-slot :initarg :first-slot)
> (second-slot :initarg :second-slot)))
> #<STANDARD-CLASS TESTCLASS 2009FAA3>
>
> CL-USER 2 >
> (defun make-test-class (&rest args)
> (make-instance 'testclass args))
> MAKE-TEST-CLASS

The obvious missing step, the one that will signal an error is:

(make-test-class)


--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

Mart van de Wege

7/18/2015 6:10:00 PM

0

"Pascal J. Bourguignon" <pjb@informatimago.com> writes:

> Mart van de Wege <mvdwege@gmail.com> writes:
>
>> Hi all,
>>
>> I'm trying to build a constructor function that calls make-instance, but
>> the number of arguments to pass to make-instance is unknown and depends
>> on the number of parameters passed to the original function.
>>
>> I can do this with a macro easily, but is it possible to do it with a
>> function?
>>
>> If I try this:
>>
>> (defclass testclass ()
>> ((first-slot :initarg :first-slot)
>> (second-slot :initarg :second-slot)))
>>
>> (defun make-test-class (&rest args)
>> (make-instance 'testclass args))
>
> (defun make-test-class (&rest args &key)
> (apply (function make-instance) 'testclass :allow-other-keys t args))

d'oh.

Obvious once you see it.

Mart

--
"We will need a longer wall when the revolution comes."
--- AJS, quoting an uncertain source.

Kenneth Tilton

7/24/2015 5:42:00 PM

0

On Saturday, July 18, 2015 at 2:14:07 PM UTC-4, Mart van de Wege wrote:
> >> I'm trying to build a constructor function that calls make-instance, but
> >> the number of arguments to pass to make-instance is unknown and depends
> >> on the number of parameters passed to the original function.
> >>
> >> I can do this with a macro easily, but is it possible to do it with a
> >> function?

Don't do it at all. Sonya Keene was wrong. CLOS is very powerful and you lose all that power when you hide make-instance behind a maker function.

-hk

Mart van de Wege

7/24/2015 6:12:00 PM

0

His Kennyness <kentilton@gmail.com> writes:

> On Saturday, July 18, 2015 at 2:14:07 PM UTC-4, Mart van de Wege wrote:
>> >> I'm trying to build a constructor function that calls make-instance, but
>> >> the number of arguments to pass to make-instance is unknown and depends
>> >> on the number of parameters passed to the original function.
>> >>
>> >> I can do this with a macro easily, but is it possible to do it with a
>> >> function?
>
> Don't do it at all. Sonya Keene was wrong. CLOS is very powerful and
> you lose all that power when you hide make-instance behind a maker
> function.
>
Well, all very nice, but I have good reasons to want to wrap
make-instance. My application domain has a shortcut to specify a number
of slot values, and the expected use case is to be able to use the short
notation to instantiate an object.

The other way around is to add a keyword argument to initialize-instance
:after, and handle the parsing of the short code and generating the
other initargs from there, but then I'm writing a constructor function
anyway.

In other words: please refrain from assuming you know the application
domain.

Mart

--
"We will need a longer wall when the revolution comes."
--- AJS, quoting an uncertain source.

Pascal J. Bourguignon

7/24/2015 6:14:00 PM

0

His Kennyness <kentilton@gmail.com> writes:

> On Saturday, July 18, 2015 at 2:14:07 PM UTC-4, Mart van de Wege wrote:
>> >> I'm trying to build a constructor function that calls make-instance, but
>> >> the number of arguments to pass to make-instance is unknown and depends
>> >> on the number of parameters passed to the original function.
>> >>
>> >> I can do this with a macro easily, but is it possible to do it with a
>> >> function?
>
> Don't do it at all. Sonya Keene was wrong. CLOS is very powerful and
> you lose all that power when you hide make-instance behind a maker
> function.

Indeed MAKE-INSTANCE let you use the factory pattern for free!

Compare:

---(factory pattern in some non-descript language)----------------------

/* Factory and car interfaces */

interface CarFactory {
public function makeCar();
}


interface Car {
public function getType();
}

/* Concrete implementations of the factory and car */

class SedanFactory implements CarFactory {
public function makeCar() {
return new Sedan();
}
}

class Sedan implements Car {
public function getType() {
return 'Sedan';
}
}

/* Client */

$factory = new SedanFactory();
$car = $factory->makeCar();
print $car->getType();

------------------------------------------------------------------------

with:

---(factory pattern in lisp)--------------------------------------------

(defclass car ()
((type :initform "generic car" :initarg :type :reader car-type)))

(defclass sedan (car)
()
(:default-initargs :type "sedan"))

(let ((factory 'sedan))
(car-type (make-instance factory)))
; --> "sedan"

------------------------------------------------------------------------


--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

Kaz Kylheku

7/24/2015 7:13:00 PM

0

On 2015-07-24, His Kennyness <kentilton@gmail.com> wrote:
> On Saturday, July 18, 2015 at 2:14:07 PM UTC-4, Mart van de Wege wrote:
>> >> I'm trying to build a constructor function that calls make-instance, but
>> >> the number of arguments to pass to make-instance is unknown and depends
>> >> on the number of parameters passed to the original function.
>> >>
>> >> I can do this with a macro easily, but is it possible to do it with a
>> >> function?
>
> Don't do it at all. Sonya Keene was wrong. CLOS is very powerful and you lose
> all that power when you hide make-instance behind a maker function.

Nope! You just have to take the class parameter in the wrapper.

(defun make (class &rest args)
(apply #'make-instance class args))

See? No power lost.