Веб Зображення Новини Групи Блоги Перекладач Gmail Ще »
Групи, які ви переглядали нещодавно | Довідка | Увійти
Головна сторінка Груп Google
macros for generating lambda functions at runtime
Занадто багато тем, що мають бути показані першими. Для того, щоб показати тему першою, зніміть цю опцію з іншої теми.
Під час обробки вашого запиту сталася помилка. Будь ласка, повторіть вашу спробу пізніше.
флаг
  24 повідомлення - Згорнути всі  -  Перекласти все вказаною мовою: Перекладено (переглянути всі оригінали)
Група, до якої ви додаєте допис, - група Usenet. Відтак, будь-хто в Інтернеті бачитиме вашу електронну адресу.
Вашу відповідь не було надіслано.
Ваш допис надіслано
 
Від:
Кому:
Копія:
Продолжить:
Додати копію: | Додати продовження: | Редагувати тему
Тема:
Підтвердження:
З метою підтвердження введіть символи, наведені на зображенні нижче, або числа, які чуєте, натиснувши значок доступу. Прослухайте і введіть цифри, що чуєте
 
Nicolas Edel  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 2 Лис, 18:06
Групи новин: comp.lang.lisp
Від: Nicolas Edel <nicolas.e...@gmail.com>
Дата: Mon, 2 Nov 2009 08:06:46 -0800 (PST)
Місцевий час: Пн 2 Лис 2009 18:06
Тема: macros for generating lambda functions at runtime
Dear group

I'd like to make some closures to speed up operations that are
specified at run time, as it is done for regex compilation. So let's
take a *very* simple exmaple:

CL-USER> (defun foo (value)
           #'(lambda (x)
               (eq x value)))
FOO
CL-USER> foo
#<CLOSURE (LAMBDA (X)) {AF278FD}>
CL-USER> (funcall (foo 1) 0)
NIL
CL-USER> (funcall (bar 1) 1)
T

So that's ok. Now let's suppose we would like the invert the test
depending on a predicate value:

CL-USER> (defun foo (value predicate)
           #'(lambda (x)
               (if predicate
                   (eq x value)
                   (not (eq x value)))))
FOO

Or, in order to avoid a test at runtime:

CL-USER> (defun foo (value predicate)
           (if predicate
               #'(lambda (x) (eq x value))
               #'(lambda (x) (not (eq x value)))))
FOO

It looks like a macro would allow to avoid code duplication here

CL-USER> (defmacro maybe (predicate statement)
           (if predicate
               `(,@statement)
               `(not ,statement)))
MAYBE
CL-USER> (macroexpand-1 '(maybe T (eq x value)))
(EQ X VALUE)
T
CL-USER> (macroexpand-1 '(maybe NIL (eq x value)))
(NOT (EQ X VALUE))
T

Now redefine foo:
CL-USER> (defun foo (value predicate)
           #'(lambda (x)
               (maybe predicate (eq x value))))
;[...]
; caught STYLE-WARNING:
;   The variable PREDICATE is defined but never used.
;[...]
STYLE-WARNING: redefining FOO in DEFUN
FOO

Calling the function shows that the variable PREDICATE is indeed
not taken into account.
Now (finally) the questions:

1. Why ?
2. How to use macros for generating the lambdas ?

Many thanks,

:Nicolas


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
x...@unnamed.xach.com  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 2 Лис, 18:38
Групи новин: comp.lang.lisp
Від: x...@unnamed.xach.com
Дата: Mon, 02 Nov 2009 11:38:47 -0500
Місцевий час: Пн 2 Лис 2009 18:38
Тема: Re: macros for generating lambda functions at runtime

There's another way to avoid code duplication: add a new higher-order
function.

  (defun foo (value)
    (lambda (x)
      (eq x value)))

  (defun predicator (predicate fun)
    (if predicate
        fun
        (complement fun)))

So your second "foo" could be:

  (defun foo-2 (value predicate)
    (predicator predicate (foo value)))

Zach


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
milanj@gmail.com  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 2 Лис, 18:42
Групи новин: comp.lang.lisp
Від: "mil...@gmail.com" <mil...@gmail.com>
Дата: Mon, 2 Nov 2009 08:42:41 -0800 (PST)
Місцевий час: Пн 2 Лис 2009 18:42
Тема: Re: macros for generating lambda functions at runtime
On Nov 2, 5:06 pm, Nicolas Edel <nicolas.e...@gmail.com> wrote:

The answer is in topic name, you cant expand macro at runtime and your
macro expansion depends on runtime value (predicate)

Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
joswig@corporate-world.li sp.de  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 2 Лис, 18:46
Групи новин: comp.lang.lisp
Від: "jos...@corporate-world.lisp.de" <jos...@lisp.de>
Дата: Mon, 2 Nov 2009 08:46:56 -0800 (PST)
Місцевий час: Пн 2 Лис 2009 18:46
Тема: Re: macros for generating lambda functions at runtime
On 2 Nov., 17:06, Nicolas Edel <nicolas.e...@gmail.com> wrote:

> Dear group

> I'd like to make some closures to speed up operations that are
> specified at run time, as it is done for regex compilation. So let's
> take a *very* simple exmaple:

> CL-USER> (defun foo (value)
>            #'(lambda (x)
>                (eq x value)))
> FOO
> CL-USER> foo
> #<CLOSURE (LAMBDA (X)) {AF278FD}>
> CL-USER> (funcall (foo 1) 0)
> NIL
> CL-USER> (funcall (bar 1) 1)

Numbers are compared with EQL, not EQ.

(if predicate ...) - you are checking a macro expansion time for the
value of predicate.

Not a good idea.

You think you now a macro expansion time the value of predicate, but
you don't. All you know is the code, but not its value.

Try:   `(if ,predicate ...  )

> MAYBE
> CL-USER> (macroexpand-1 '(maybe T (eq x value)))
> (EQ X VALUE)
> T
> CL-USER> (macroexpand-1 '(maybe NIL (eq x value)))
> (NOT (EQ X VALUE))
> T

> Now redefine foo:
> CL-USER> (defun foo (value predicate)
>            #'(lambda (x)
>                (maybe predicate (eq x value))))

The macro maybe is used.

It has two parameters: predicate and statement.

The arguments are predicate and (eq x value)

predicate = predicate

statement = (eq x value)

Remember above

(if predicate ... )   ?

predicate evaluates to the symbol predicate, which is always true.

It is similar to (if 'predicate ...) ....


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Captain Obvious  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 2 Лис, 20:24
Групи новин: comp.lang.lisp
Від: "Captain Obvious" <udode...@users.sourceforge.net>
Дата: Mon, 2 Nov 2009 20:24:30 +0200
Місцевий час: Пн 2 Лис 2009 20:24
Тема: Re: macros for generating lambda functions at runtime
 NE> 1. Why ?

Because macros work at macroexpansion time, NOT
runtime.

 NE> 2. How to use macros for generating the lambdas ?

You can use macro to generate a code which generates lambda,
for example.


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Nicolas Edel  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 10:16
Групи новин: comp.lang.lisp
Від: Nicolas Edel <nicolas.e...@gmail.com>
Дата: Tue, 3 Nov 2009 00:16:08 -0800 (PST)
Місцевий час: Вт 3 Лис 2009 10:16
Тема: Re: macros for generating lambda functions at runtime
On Nov 2, 7:24 pm, "Captain Obvious" <udode...@users.sourceforge.net>
wrote:

>  NE> 1. Why ?

> Because macros work at macroexpansion time, NOT
> runtime.

>  NE> 2. How to use macros for generating the lambdas ?

> You can use macro to generate a code which generates lambda,
> for example.

Ok, so I use macro to generate code and then invoke the compiler at
runtime.
What is best practice for this: eval or compile ? Do they have similar
meaning in this context ?

(defun foo (predicate value)
           (eval `(function (lambda (x)
                    (maybe ,predicate (eql x ,value))))))

or

(defun foo (predicate value)
           (compile nil `(lambda (x)
                           (maybe ,predicate (eql x ,value)))))

:Nicolas


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Pascal Costanza  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 10:31
Групи новин: comp.lang.lisp
Від: Pascal Costanza <p...@p-cos.net>
Дата: Tue, 03 Nov 2009 09:31:54 +0100
Місцевий час: Вт 3 Лис 2009 10:31
Тема: Re: macros for generating lambda functions at runtime

The semantics are the same. Which one is better depends on context. If
you use these functions only one or two times, or so, it's not
worthwhile to compile them, because compilation creates a considerable
overhead by itself. If you use them more often, then compilation is
worthwhile (although I recently heard that in, say, ECL or GCL,
compilation is almost always prohibitive).

You can also say (coerce '(lambda ...) 'function), and let the CL
implementation itself decide.

Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Nicolas Edel  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 10:46
Групи новин: comp.lang.lisp
Від: Nicolas Edel <nicolas.e...@gmail.com>
Дата: Tue, 3 Nov 2009 00:46:38 -0800 (PST)
Місцевий час: Вт 3 Лис 2009 10:46
Тема: Re: macros for generating lambda functions at runtime
On Nov 3, 9:31 am, Pascal Costanza <p...@p-cos.net> wrote:

At that time, I don't know if they will be used often. But if they are
to be used in a context such as packet filtering, there will be a slow
startup time but this will be runtime efficient. I wanted to learn how
to make this now to avoid problems at experimentation time.

> You can also say (coerce '(lambda ...) 'function), and let the CL
> implementation itself decide.

Nice, indeed. But before I let the implementation decide by itself, I
would like to know if there are fundamental differences when calling
eval and compile in this context.

:Nicolas


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Barry Margolin  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 11:07
Групи новин: comp.lang.lisp
Від: Barry Margolin <bar...@alum.mit.edu>
Дата: Tue, 03 Nov 2009 04:07:38 -0500
Місцевий час: Вт 3 Лис 2009 11:07
Тема: Re: macros for generating lambda functions at runtime
In article
<b4f59fea-7673-4a75-91f4-ca3983a24...@k17g2000yqb.googlegroups.com>,
 Nicolas Edel <nicolas.e...@gmail.com> wrote:

No semantic differences, just performance differences.  Compile will
create a compiled function, eval will create an interpreted function in
some implementations.

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Tobias C. Rittweiler  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 11:21
Групи новин: comp.lang.lisp
Від: "Tobias C. Rittweiler" <t...@freebits.de.invalid>
Дата: Tue, 03 Nov 2009 10:21:55 +0100
Місцевий час: Вт 3 Лис 2009 11:21
Тема: Re: macros for generating lambda functions at runtime

Barry Margolin <bar...@alum.mit.edu> writes:
>  Nicolas Edel <nicolas.e...@gmail.com> wrote:

> > Nice, indeed. But before I let the implementation decide by itself, I
> > would like to know if there are fundamental differences when calling
> > eval and compile in this context.

> No semantic differences, just performance differences.  Compile will
> create a compiled function, eval will create an interpreted function in
> some implementations.

COMPILED-FUNCTION-P will return T on the first kind, but NIL on the
other kind! That's as big semantical change as you can get. ;-)

  -T.


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Captain Obvious  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 11:25
Групи новин: comp.lang.lisp
Від: "Captain Obvious" <udode...@users.sourceforge.net>
Дата: Tue, 3 Nov 2009 11:25:25 +0200
Місцевий час: Вт 3 Лис 2009 11:25
Тема: Re: macros for generating lambda functions at runtime
 ??>> You can use macro to generate a code which generates lambda,
 ??>> for example.

 NE> Ok, so I use macro to generate code and then invoke the compiler at
 NE> runtime.

No! You use macro to transform your code at compile time.
Then code you've generated does anything it wants in runtime.

 NE> What is best practice for this: eval or compile ?

In case you _really_ need it, best practice is compile.
But you do not need it in this case.
A rule of thumb: if you think you need eval or compile,
it is higly lickely you're doing it wrong.

Basically, the only case when you need eval is when
code is not known at compile-time.  That is, user
enters it from keyboard, or you recieve it from network,
or generate through GA or something. In other cases,
when you just need to fill in some parameters, you
can do that other way.

 NE>  Do they have similar meaning in this context ?

Yep they do, almost. The only difference is that
eval might or might not compile functions, while compile
almost certainly does. compile is a bit tidier IMHO
because it accepts only lambda rather than arbitrary
piece of code. There is also a third way to do it -- (coerce ... 'function),
it is pretty good too, if you just need a function, not necessarily
compiled.

That's how you can generate lambdas at runtime,
but there is no reason to do this in this case.

Xach have shown how you can do this with lambda
and without any code duplication. That was really the best way.
It is actually a good practice to avoid using macros when
you can just use higher-order functions.

If you absolutely want to use macros, you can do this like
this (using IF at runtime):

(defmacro maybe-lambda (predicate paramlist statement)
      `(if ,predicate
                (lambda ,paramlist ,statement)
                (lambda ,paramlist (not ,statement))))

(defun foo (value predicate)
  (maybe-lambda predicate (x) (eql x value)))

No runtime code generation, but maybe have lost its generality.

Or you can write a more complex macro which is more general.
Your `maybe` macro just maybe  inserts NOT in the beginning
of the statement.
My with-maybe macro can insert NOT into any place within
statement user wants it to.

(defmacro with-maybe (predicate statement)
  `(if ,predicate
    (macrolet ((maybe (statement) statement))
      ,statement)
    (macrolet ((maybe (statement) `(not ,statement)))
      ,statement)))

You use it like this:

(defun foo (value predicate)
  (with-maybe predicate
    (lambda (x) (maybe (eql x value)))))

Macro generates a code which has IF switching between two
branches. Branches are made different by different MAYBE
local macros defined via MACROLET -- in first branch MAYBE is no-op,
so it is vanilla statement. In second branch MAYBE adds NOT to
the statement.

Unfortunately there is no tool one can use to get fully macroexpanded
code (at least I don't know any), but once you'll replace macrolet:ed
maybe:s, you'll get exactly function you had wrote yourself:

(defun foo (value predicate)
       (if predicate
            (lambda (x) (eq x value))
            (lambda (x) (not (eq x value)))))

 NE> (defun foo (predicate value)
 NE>     (eval `(function (lambda (x)
 NE>       (maybe ,predicate (eql x ,value))))))

By the way, if you're generating code anyway, you do not really
need macro, you can do this with ordinary function or just construct
in-place:

 (defun foo (predicate value)
     (eval `(function (lambda (x)
            ,(let ((code `(eql x, value))
               (if predicate
                   code
                   `(not ,code)))))


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Pascal Costanza  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 12:47
Групи новин: comp.lang.lisp
Від: Pascal Costanza <p...@p-cos.net>
Дата: Tue, 03 Nov 2009 11:47:27 +0100
Місцевий час: Вт 3 Лис 2009 12:47
Тема: Re: macros for generating lambda functions at runtime

Tobias C. Rittweiler wrote:
> Barry Margolin <bar...@alum.mit.edu> writes:

>>  Nicolas Edel <nicolas.e...@gmail.com> wrote:

>>> Nice, indeed. But before I let the implementation decide by itself, I
>>> would like to know if there are fundamental differences when calling
>>> eval and compile in this context.
>> No semantic differences, just performance differences.  Compile will
>> create a compiled function, eval will create an interpreted function in
>> some implementations.

> COMPILED-FUNCTION-P will return T on the first kind, but NIL on the
> other kind!

Not quite: It may actually return T in some implementations for the
second kind. A CL implementation is required to support at least minimal
compilation (as per 3.2.2.2 in the HyperSpec), but is not required to
support a 'pure' interpreter (as per 3.1 in the HyperSpec) and can
actually always perform (at least minimal) compilation.

> That's as big semantical change as you can get. ;-)

Still not that big. ;)

Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Pascal Costanza  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 13:02
Групи новин: comp.lang.lisp
Від: Pascal Costanza <p...@p-cos.net>
Дата: Tue, 03 Nov 2009 12:02:41 +0100
Місцевий час: Вт 3 Лис 2009 13:02
Тема: Re: macros for generating lambda functions at runtime

If you want your code to be very sophisticated, you can actually also
implement your own version that uses interpreted code by default, counts
how often a particular runtime-generated function is called, and after a
certain threshold, compiles into a more efficient version (under the
assumption that it will continue to be called even more often).

Here is a sketch [untested]:

(defclass smart-function (funcallable-standard-object) ()
   (:metaclass funcallable-standard-class))

(defparameter *threshold* 10)

(defun make-smart-function (body)
   (let ((fun (make-instance 'smart-function)))
     (set-funcallable-instance-function
       fun
       (let ((counter 0) (funfun (eval body)))
         (lambda (&rest args)
           (declare (dynamic-extent args)
           (when (> (incf counter) *threshold*)
             (unless (compiled-function-p funfun)
               (setq funfun (compile nil body)))
             (set-funcallable-instance-function fun funfun))
           (apply funfun args))))
     fun))

(defmacro smart-lambda ((&rest args) &body body)
   `(make-smart-function `(lambda ,args ,@body)))

Yes, this requires the CLOS MOP. ;)

Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Nicolas Edel  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 14:37
Групи новин: comp.lang.lisp
Від: Nicolas Edel <nicolas.e...@gmail.com>
Дата: Tue, 3 Nov 2009 04:37:08 -0800 (PST)
Місцевий час: Вт 3 Лис 2009 14:37
Тема: Re: macros for generating lambda functions at runtime
On Nov 3, 6:02 am, Pascal Costanza <p...@p-cos.net> wrote:

Looks nice, but I am not shure I am already comfortable enough at Lisp
programing to use such tricks. Thanks anyway ;)

:Nicolas


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Juanjo  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 15:07
Групи новин: comp.lang.lisp
Від: Juanjo <juanjose.garciarip...@googlemail.com>
Дата: Tue, 3 Nov 2009 05:07:23 -0800 (PST)
Місцевий час: Вт 3 Лис 2009 15:07
Тема: Re: macros for generating lambda functions at runtime
On Nov 3, 9:31 am, Pascal Costanza <p...@p-cos.net> wrote:

It is not "almost always prohibitive". The cost is basically executing
a C compiler. And that is worthwhile if you need the function often
and if the function it is low level enough that it profits from
compilation.

What is prohibitive is to compile using C a function that you are
going to use only once, and do it for every use.

The alternative then is to use bytcompiled functions, which do save
some time, but are not as efficient as natively compiled ones. You can
always do this, without much hassle. One cheap way is to coerce a
lambda form to a function type.

> (coerce '(lambda (x) (1+ x)) 'function)

#<bytecompiled-function 0000000102a301e0>

> (funcall * 2)

3

Juanjo


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Pascal Costanza  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 16:25
Групи новин: comp.lang.lisp
Від: Pascal Costanza <p...@p-cos.net>
Дата: Tue, 03 Nov 2009 15:25:55 +0100
Місцевий час: Вт 3 Лис 2009 16:25
Тема: Re: macros for generating lambda functions at runtime

OK, thanks a lot for the clarification, and also for the hint about byte
compilation, which is certainly useful!

Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Pillsy  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 17:59
Групи новин: comp.lang.lisp
Від: Pillsy <pillsb...@gmail.com>
Дата: Tue, 3 Nov 2009 07:59:31 -0800 (PST)
Місцевий час: Вт 3 Лис 2009 17:59
Тема: Re: macros for generating lambda functions at runtime
On Nov 3, 6:02 am, Pascal Costanza <p...@p-cos.net> wrote:
[...]

What's the advantage of using the MOP over a straight-up closure in
this instance?

Thanks,
Pillsy


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Pascal Costanza  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 18:14
Групи новин: comp.lang.lisp
Від: Pascal Costanza <p...@p-cos.net>
Дата: Tue, 03 Nov 2009 17:14:20 +0100
Місцевий час: Вт 3 Лис 2009 18:14
Тема: Re: macros for generating lambda functions at runtime

Good question. Maybe there is none. Originally I thought I had to store
the body in a slot of the smart-function instance, but that turned out
not to be necessary. So indeed, maybe you can replace this by a plain
closure.

Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Pascal Costanza  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 3 Лис, 18:58
Групи новин: comp.lang.lisp
Від: Pascal Costanza <p...@p-cos.net>
Дата: Tue, 03 Nov 2009 17:58:01 +0100
Місцевий час: Вт 3 Лис 2009 18:58
Тема: Re: macros for generating lambda functions at runtime

Yes, I guess this should work:

(defparameter *threshold* 10)

(defun make-smart-function (body)
   (let ((counter 0) fun funfun)
     (setq funfun (eval body)
           fun (lambda (&rest args)
                 (declare (dynamic-extent args))
                 (when (> (incf counter) *threshold*)
                   (unless (compiled-function-p funfun)
                     (setq funfun (compile nil body))
                     (setq fun funfun)))
                 (apply funfun args)))
     (lambda (&rest args)
       (declare (dynamic-extent args))
       (apply fun args))))

(defmacro smart-lambda ((&rest args) &body body)
   `(make-smart-function (lambda ,args ,@body)))

Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Captain Obvious  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 4 Лис, 00:21
Групи новин: comp.lang.lisp
Від: "Captain Obvious" <udode...@users.sourceforge.net>
Дата: Wed, 4 Nov 2009 00:21:27 +0200
Місцевий час: Ср 4 Лис 2009 00:21
Тема: Re: macros for generating lambda functions at runtime
 P> What's the advantage of using the MOP over a straight-up closure in
 P> this instance?

Might have better performance. If you use &rest and then apply
I guess most compilers will make a list, that is, you have more consing.

(lambda (&rest args)
   (let ((fn ....))
      (apply fn args)))

But if you're doing it via macro, you can use certain number of parameters
directly:

(lambda (a b c)
   (let ((fn ....))
      (funcall fn a b c)))

Then  there is no consing. There might be some overhead from using closure's
variable and funcall, but I guess funcallable-object's funcall is not
totally overheadless
either. So probably funcallable-object offers only a minuscule advantage in
this case.


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Kaz Kylheku  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 5 Лис, 03:25
Групи новин: comp.lang.lisp
Від: Kaz Kylheku <kkylh...@gmail.com>
Дата: Thu, 5 Nov 2009 01:25:51 +0000 (UTC)
Місцевий час: Чт 5 Лис 2009 03:25
Тема: Re: macros for generating lambda functions at runtime
On 2009-11-03, Captain Obvious <udode...@users.sourceforge.net> wrote:

>  P> What's the advantage of using the MOP over a straight-up closure in
>  P> this instance?

> Might have better performance. If you use &rest and then apply
> I guess most compilers will make a list, that is, you have more consing.

> (lambda (&rest args)
>    (let ((fn ....))
>       (apply fn args)))

It's a poor Lisp compiler which conses a list for code which only passes the
&rest argument down to another function with apply.

Pascal's code went right over your head there. The advantage of the MOP
solution has nothing to do with this. And it has &rest/apply processing buried
in it.

What Pascal's code does is allow the user's function to be called several times
without being compiled. It counts how many calls there are. When the calls
exceed a threshold, then the object compiles the function.

When the function is compiled, the object is able to replace its own closure
with that compiled function. So subsequent calls go directly to that function,
bypassing the threshold check.

You can't do that with a lambda closure, because a lambda closure cannot
replace future calls to itself with a different closure.


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Kaz Kylheku  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 5 Лис, 03:39
Групи новин: comp.lang.lisp
Від: Kaz Kylheku <kkylh...@gmail.com>
Дата: Thu, 5 Nov 2009 01:39:09 +0000 (UTC)
Місцевий час: Чт 5 Лис 2009 03:39
Тема: Re: macros for generating lambda functions at runtime
On 2009-11-03, Pascal Costanza <p...@p-cos.net> wrote:

Uh, you can do this with the existing standard funcallable objects.  Namely,
instances of this highly curious SYMBOL class, which have a standard
slot given by the accessor SYMBOL-FUNCTION. :)

;; tested modifications to untested code
;; fixed unbalanced parentheses in declare
;; extra levels of unquote added to backquote
;; class replaced by symbol

(defparameter *threshold* 10)

(defun make-smart-function (body)
  (let ((fun (gensym "SMART-FUNCTION-")))
    (setf
      (symbol-function fun)
      (let ((counter 0) (funfun (eval body)))
        (lambda (&rest args)
          (declare (dynamic-extent args))
          (when (> (incf counter) *threshold*)
            (unless (compiled-function-p funfun)
              (setq funfun (compile nil body)))
            (setf (symbol-function fun) funfun))
          (apply funfun args))))
    fun))

(defmacro smart-lambda ((&rest args) &body body)
  `(make-smart-function `(lambda ,',args ,',@body)))

Test:

[4]> (defparameter x (smart-lambda (a b c) (list a b c)))
X
[5]> (symbol-function x)
#<FUNCTION :LAMBDA (&REST ARGS) (DECLARE (DYNAMIC-EXTENT ARGS))
  (WHEN (> (INCF COUNTER) *THRESHOLD*)
   (UNLESS (COMPILED-FUNCTION-P FUNFUN) (SETQ FUNFUN (COMPILE NIL BODY)))
   (SETF (SYMBOL-FUNCTION FUN) FUNFUN))
  (APPLY FUNFUN ARGS)>
[6]> (funcall x 1 2 3)
(1 2 3)
[7]> (funcall x 1 2 3)
(1 2 3)
[8]> (symbol-function x)
#<FUNCTION :LAMBDA (&REST ARGS) (DECLARE (DYNAMIC-EXTENT ARGS))
  (WHEN (> (INCF COUNTER) *THRESHOLD*)
   (UNLESS (COMPILED-FUNCTION-P FUNFUN) (SETQ FUNFUN (COMPILE NIL BODY)))
   (SETF (SYMBOL-FUNCTION FUN) FUNFUN))
  (APPLY FUNFUN ARGS)>
[9]> *threshold*
10
[10]> (symbol-function x)
#<FUNCTION :LAMBDA (&REST ARGS) (DECLARE (DYNAMIC-EXTENT ARGS))
  (WHEN (> (INCF COUNTER) *THRESHOLD*)
   (UNLESS (COMPILED-FUNCTION-P FUNFUN) (SETQ FUNFUN (COMPILE NIL BODY)))
   (SETF (SYMBOL-FUNCTION FUN) FUNFUN))
  (APPLY FUNFUN ARGS)>
[11]> (funcall x 1 2 3)
(1 2 3)
[12]> (funcall x 1 2 3)
(1 2 3)
[13]> (funcall x 1 2 3)
(1 2 3)
[14]> (funcall x 1 2 3)
(1 2 3)
[15]> (funcall x 1 2 3)
(1 2 3)
[16]> (funcall x 1 2 3)
(1 2 3)
[17]> (funcall x 1 2 3)
(1 2 3)
[18]> (funcall x 1 2 3)
(1 2 3)
[19]> (funcall x 1 2 3)
(1 2 3)
[20]> (funcall x 1 2 3)
(1 2 3)
[21]> (funcall x 1 2 3)
(1 2 3)
[22]> (symbol-function x)
#<COMPILED-FUNCTION NIL>
[23]> (funcall x 1 2 3)
(1 2 3)


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Pascal Costanza  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 5 Лис, 10:56
Групи новин: comp.lang.lisp
Від: Pascal Costanza <p...@p-cos.net>
Дата: Thu, 05 Nov 2009 09:56:18 +0100
Місцевий час: Чт 5 Лис 2009 10:56
Тема: Re: macros for generating lambda functions at runtime

In principle yes, but unfortunately, there is a border case that doesn't
quite work with symbols as functions:

(defclass my-fun (funcallable-standard-object)
   ()
   (:metaclass funcallable-standard-class))

(defmethod initialize-instance :after ((f my-fun) &key)
   (set-funcallable-instance-function f (lambda () 42)))

* (setf (symbol-function 'foo) (make-instance 'my-fun))

#<MY-FUN {1002F44C09}>
* (foo)

42
* (setf (symbol-function 'bar) 'foo)
; in: LAMBDA NIL
;     (FUNCALL #'(SETF SYMBOL-FUNCTION) #:NEW671
'CLOSER-COMMON-LISP-USER::BAR)
; --> SB-C::%FUNCALL
; ==>
;   (#<SB-C::GLOBAL-VAR
;      :%SOURCE-NAME (SETF SYMBOL-FUNCTION)
;      :TYPE #<SB-KERNEL:FUN-TYPE (FUNCTION #'SYMBOL #)>
;      :WHERE-FROM :DECLARED
;      :KIND :GLOBAL-FUNCTION {1002F4A281}>
;    #:NEW671 'CLOSER-COMMON-LISP-USER::BAR)
;
; caught WARNING:
;   Asserted type FUNCTION conflicts with derived type
;   (VALUES (MEMBER FOO) &OPTIONAL).
;   See also:
;     The SBCL Manual, Node "Handling of Types"
;
; compilation unit finished
;   caught 1 WARNING condition

debugger invoked on a TYPE-ERROR: The value FOO is not of type FUNCTION.

Some Common Lisp implementations accept this, some don't. Those that
don't accept this are right not to do so, according to the HyperSpec. (I
think this is an unnecessary restriction, symbols should be accepted as
symbol-functions, but that's maybe just me... ;)

Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Captain Obvious  
Переглянути профіль   Перекласти вказаною мовою: Перекладено (переглянути оригінал)
 Більше налаштувань 6 Лис, 14:33
Групи новин: comp.lang.lisp
Від: "Captain Obvious" <udode...@users.sourceforge.net>
Дата: Fri, 6 Nov 2009 14:33:25 +0200
Місцевий час: Пт 6 Лис 2009 14:33
Тема: Re: macros for generating lambda functions at runtime
 ??>> Might have better performance. If you use &rest and then apply
 ??>> I guess most compilers will make a list, that is, you have more
 ??>> consing.
 ??>>
 ??>> (lambda (&rest args)
 ??>>    (let ((fn ....))
 ??>>       (apply fn args)))

 KK> It's a poor Lisp compiler which conses a list for code which only
 KK> passes the &rest argument down to another function with apply.

Can you please show an example of a compiler which optimizes it?

 KK> You can't do that with a lambda closure, because a lambda closure
 KK> cannot replace future calls to itself with a different closure.

That's why we have not one closure, but two closures, with first
calling the second one -- then we can replace second closure with
a compiled version when we would want to. There is overhead
of indirection, but arguably it is very low.

Here's code by Pascal:

(defparameter *threshold* 10)

(defun make-smart-function (body)
   (let ((counter 0) fun funfun)
     (setq funfun (eval body)
           fun (lambda (&rest args)
                 (declare (dynamic-extent args))
                 (when (> (incf counter) *threshold*)
                   (unless (compiled-function-p funfun)
                     (setq funfun (compile nil body))
                     (setq fun funfun)))
                 (apply funfun args)))
     (lambda (&rest args)
       (declare (dynamic-extent args))
       (apply fun args))))

(defmacro smart-lambda ((&rest args) &body body)
   `(make-smart-function (lambda ,args ,@body)))

Let's see does it go over your head or not.


Ви мусите увійти перед публікацією повідомлень.
Аби надіслати допис, будь ласка, спочатку приєднайтеся до цієї групи.
Будь ласка, поновіть своє прізвисько на сторінці налаштування передплати перед тим, як надіслати свій допис.
У вас немає права надсилання дописів до цієї групи.
Кінець повідомлень
« Повернутися до обговорень « Новіша тема     Старіша тема »

Створити групу - Групи Google - Домашня сторінка Google - Правила користування послугою - Заява про конфіденційність і нерозголошення інформації
©2009 Google