Rocksolid Light

Welcome to RetroBBS

mail  files  register  newsreader  groups  login

Message-ID:  

You are false data.


devel / comp.lang.lisp / First own macro: How evil is eval?

SubjectAuthor
* First own macro: How evil is eval?Axel Reichert
+* Re: First own macro: How evil is eval?Jeff Barnett
|`* Re: First own macro: How evil is eval?Axel Reichert
| `- Re: First own macro: How evil is eval?Jeff Barnett
+* Re: First own macro: How evil is eval?Spiros Bousbouras
|`* Re: First own macro: How evil is eval?Axel Reichert
| `- Re: First own macro: How evil is eval?Axel Reichert
+* Re: First own macro: How evil is eval?Kaz Kylheku
|`- Re: First own macro: How evil is eval?Axel Reichert
`* Re: First own macro: How evil is eval?Stefan Ram
 +- Re: First own macro: How evil is eval?Axel Reichert
 `* Re: First own macro: How evil is eval?Kaz Kylheku
  `- Re: First own macro: How evil is eval?Stefan Ram

1
First own macro: How evil is eval?

<m2h7bvc3rs.fsf@axel-reichert.de>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=16716&group=comp.lang.lisp#16716

  copy link   Newsgroups: comp.lang.lisp
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: mail@axel-reichert.de (Axel Reichert)
Newsgroups: comp.lang.lisp
Subject: First own macro: How evil is eval?
Date: Sun, 28 Nov 2021 23:29:59 +0100
Organization: A noiseless patient Spider
Lines: 75
Message-ID: <m2h7bvc3rs.fsf@axel-reichert.de>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="e07d59b20ac8fd6788941b649248b220";
logging-data="7706"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/J55XTKj6MCwWyGuIOPwlBaGUAJTVAgRQ="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (darwin)
Cancel-Lock: sha1:WyT1mSQGnNuilq2BRNCYDkVyhKc=
sha1:sORlwxCEEgipUi7IDt1qkp5+UFc=
 by: Axel Reichert - Sun, 28 Nov 2021 22:29 UTC

Hello,

finally I felt the need to write my first macro. I have read Practical
Common Lisp's chapters 7 and 8 and made my way up to half of chapter 7
of "On Lisp", sometimes think I got it, but when trying a write it down
I struggle a lot, so Perlism 116 applies:

http://www.cs.yale.edu/homes/perlis-alan/quotes.html

(-:

Here is what I am trying (all simplified): I have an expensive function,
say

(defun expensive-defun (list)
(sleep 3)
(mapcar #'1+ list))

that is called over and over again by

(defun frequently-run-defun (number)
(case number
(1 (expensive-defun (list 0 1 2)))
(2 (expensive-defun (list 1 2 3)))
(3 (expensive-defun (list 2 3 4)))))

In fact, it would be possible and of course faster at runtime to
calculate the results in advance, such as

(defun frequently-run-defun-fast (number)
(case number
(1 '(1 2 3))
(2 '(2 3 4))
(3 '(3 4 5))))

But the original representation as (list 0 1 2), ... would feel much
more natural (in the sense of domain-specific thinking) in the source
code and so I had the idea to write a macro that transforms

(cheap-macro (list 0 1 2))

or

(cheap-macro '(0 1 2))

into

'(1 2 3)

and then have

(defun frequently-run-defun-macro (number)
(case number
(1 (cheap-macro (list 0 1 2)))
(2 (cheap-macro (list 1 2 3)))
(3 (cheap-macro (list 2 3 4)))))

which gives me more intuitively readable AND faster running code,
so the best of both worlds.

I tried (more poking around in the dark) various combinations of quotes,
backquotes and commas, but failed miserably. What did work was

(defmacro cheap-macro (list)
`(quote ,(eval `(mapcar #'1+ ,list))))

but I cannot belief that I will have to fall back to eval for such a
trivial macro. It is much more likely that I am still lacking
understanding.

What would be the "best-practice" way to implement this macro?

Best regards

Axel

Re: First own macro: How evil is eval?

<so13e0$s99$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=16717&group=comp.lang.lisp#16717

  copy link   Newsgroups: comp.lang.lisp
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: jbb@notatt.com (Jeff Barnett)
Newsgroups: comp.lang.lisp
Subject: Re: First own macro: How evil is eval?
Date: Sun, 28 Nov 2021 16:30:08 -0700
Organization: A noiseless patient Spider
Lines: 77
Message-ID: <so13e0$s99$1@dont-email.me>
References: <m2h7bvc3rs.fsf@axel-reichert.de>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Sun, 28 Nov 2021 23:30:08 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="01388cb8c6575114ef6af6dd75a686a0";
logging-data="28969"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19B748crbxwn/f+4fcESFZj50jdBS0q7TE="
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.3.2
Cancel-Lock: sha1:jqiFBqvh6nKb5RH0wVZysuYONKc=
In-Reply-To: <m2h7bvc3rs.fsf@axel-reichert.de>
Content-Language: en-US
 by: Jeff Barnett - Sun, 28 Nov 2021 23:30 UTC

On 11/28/2021 3:29 PM, Axel Reichert wrote:
> Hello,
>
> finally I felt the need to write my first macro. I have read Practical
> Common Lisp's chapters 7 and 8 and made my way up to half of chapter 7
> of "On Lisp", sometimes think I got it, but when trying a write it down
> I struggle a lot, so Perlism 116 applies:
>
> http://www.cs.yale.edu/homes/perlis-alan/quotes.html
>
> (-:
>
> Here is what I am trying (all simplified): I have an expensive function,
> say
>
> (defun expensive-defun (list)
> (sleep 3)
> (mapcar #'1+ list))
>
> that is called over and over again by
>
> (defun frequently-run-defun (number)
> (case number
> (1 (expensive-defun (list 0 1 2)))
> (2 (expensive-defun (list 1 2 3)))
> (3 (expensive-defun (list 2 3 4)))))
>
> In fact, it would be possible and of course faster at runtime to
> calculate the results in advance, such as
>
> (defun frequently-run-defun-fast (number)
> (case number
> (1 '(1 2 3))
> (2 '(2 3 4))
> (3 '(3 4 5))))
>
> But the original representation as (list 0 1 2), ... would feel much
> more natural (in the sense of domain-specific thinking) in the source
> code and so I had the idea to write a macro that transforms
>
> (cheap-macro (list 0 1 2))
>
> or
>
> (cheap-macro '(0 1 2))
>
> into
>
> '(1 2 3)
>
> and then have
>
> (defun frequently-run-defun-macro (number)
> (case number
> (1 (cheap-macro (list 0 1 2)))
> (2 (cheap-macro (list 1 2 3)))
> (3 (cheap-macro (list 2 3 4)))))
>
> which gives me more intuitively readable AND faster running code,
> so the best of both worlds.
>
> I tried (more poking around in the dark) various combinations of quotes,
> backquotes and commas, but failed miserably. What did work was
>
> (defmacro cheap-macro (list)
> `(quote ,(eval `(mapcar #'1+ ,list))))
>
> but I cannot belief that I will have to fall back to eval for such a
> trivial macro. It is much more likely that I am still lacking
> understanding.
>
> What would be the "best-practice" way to implement this macro?

I suggest you look up "memo functions" and see if that technology would
help you.
--
Jeff Barnett

Re: First own macro: How evil is eval?

<m2czmjbzky.fsf@axel-reichert.de>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=16718&group=comp.lang.lisp#16718

  copy link   Newsgroups: comp.lang.lisp
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: mail@axel-reichert.de (Axel Reichert)
Newsgroups: comp.lang.lisp
Subject: Re: First own macro: How evil is eval?
Date: Mon, 29 Nov 2021 01:00:29 +0100
Organization: A noiseless patient Spider
Lines: 18
Message-ID: <m2czmjbzky.fsf@axel-reichert.de>
References: <m2h7bvc3rs.fsf@axel-reichert.de> <so13e0$s99$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="d6d359c300c55a020dfbf7442b9d8e8c";
logging-data="13533"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+vLeI0J0jHZaLY+PU5Zhl8EqEW0HKwbrc="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (darwin)
Cancel-Lock: sha1:q6yp6f7k3L2YgyPyisS5+ilTBH0=
sha1:kat5/UXdbvqWex4ACvzwYYlDvBU=
 by: Axel Reichert - Mon, 29 Nov 2021 00:00 UTC

Jeff Barnett <jbb@notatt.com> writes:

> I suggest you look up "memo functions" and see if that technology
> would help you.

Are you referring to "memoization"? I am aware of the concept, but
dismissed it so far, because I am using the lists resulting from the
"case" form for some lookup with a more or less random number, so not
repeating often. Roughly like

(position-if #'(lambda (elt) (> elt (random 1.0)))
resulting-list-from-case-form)

However, I might put this technique to good use for the "case" form
itself. Thanks for the idea, which is somewhat orthogonal to my original
question.

Axel

Re: First own macro: How evil is eval?

<so191v$4al$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=16719&group=comp.lang.lisp#16719

  copy link   Newsgroups: comp.lang.lisp
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: jbb@notatt.com (Jeff Barnett)
Newsgroups: comp.lang.lisp
Subject: Re: First own macro: How evil is eval?
Date: Sun, 28 Nov 2021 18:06:07 -0700
Organization: A noiseless patient Spider
Lines: 22
Message-ID: <so191v$4al$1@dont-email.me>
References: <m2h7bvc3rs.fsf@axel-reichert.de> <so13e0$s99$1@dont-email.me>
<m2czmjbzky.fsf@axel-reichert.de>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Mon, 29 Nov 2021 01:06:07 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="01388cb8c6575114ef6af6dd75a686a0";
logging-data="4437"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/6QALPF2VnLEwAIUONaTMUBEXRA2aYReA="
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:91.0) Gecko/20100101
Thunderbird/91.3.2
Cancel-Lock: sha1:qFnmrT3K2xTr19zDdwxa8N9cntk=
In-Reply-To: <m2czmjbzky.fsf@axel-reichert.de>
Content-Language: en-US
 by: Jeff Barnett - Mon, 29 Nov 2021 01:06 UTC

On 11/28/2021 5:00 PM, Axel Reichert wrote:
> Jeff Barnett <jbb@notatt.com> writes:
>
>> I suggest you look up "memo functions" and see if that technology
>> would help you.
>
> Are you referring to "memoization"? I am aware of the concept, but
> dismissed it so far, because I am using the lists resulting from the
> "case" form for some lookup with a more or less random number, so not
> repeating often. Roughly like
>
> (position-if #'(lambda (elt) (> elt (random 1.0)))
> resulting-list-from-case-form)
>
> However, I might put this technique to good use for the "case" form
> itself. Thanks for the idea, which is somewhat orthogonal to my original
> question.

Yes I was talking about memo functions and I was thinking of using them
to save some of the work done by expensive-defun.
--
Jeff Barnett

Re: First own macro: How evil is eval?

<8oTDiWCWd=lP89b5e@bongo-ra.co>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=16720&group=comp.lang.lisp#16720

  copy link   Newsgroups: comp.lang.lisp
Path: i2pn2.org!i2pn.org!aioe.org!NFyD4+LU+vfu+oVKTmfrbQ.user.46.165.242.91.POSTED!not-for-mail
From: spibou@gmail.com (Spiros Bousbouras)
Newsgroups: comp.lang.lisp
Subject: Re: First own macro: How evil is eval?
Date: Mon, 29 Nov 2021 12:58:28 -0000 (UTC)
Organization: Aioe.org NNTP Server
Message-ID: <8oTDiWCWd=lP89b5e@bongo-ra.co>
References: <m2h7bvc3rs.fsf@axel-reichert.de>
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
Injection-Info: gioia.aioe.org; logging-data="11114"; posting-host="NFyD4+LU+vfu+oVKTmfrbQ.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org";
X-Organisation: Weyland-Yutani
X-Notice: Filtered by postfilter v. 0.9.2
X-Server-Commands: nowebcancel
 by: Spiros Bousbouras - Mon, 29 Nov 2021 12:58 UTC

On Sun, 28 Nov 2021 23:29:59 +0100
Axel Reichert <mail@axel-reichert.de> wrote:
> Here is what I am trying (all simplified): I have an expensive function,
> say
>
> (defun expensive-defun (list)
> (sleep 3)
> (mapcar #'1+ list))
>
> that is called over and over again by
>
> (defun frequently-run-defun (number)
> (case number
> (1 (expensive-defun (list 0 1 2)))
> (2 (expensive-defun (list 1 2 3)))
> (3 (expensive-defun (list 2 3 4)))))
>
> In fact, it would be possible and of course faster at runtime to
> calculate the results in advance, such as
>
> (defun frequently-run-defun-fast (number)
> (case number
> (1 '(1 2 3))
> (2 '(2 3 4))
> (3 '(3 4 5))))
>
> But the original representation as (list 0 1 2), ... would feel much
> more natural (in the sense of domain-specific thinking) in the source
> code and so I had the idea to write a macro that transforms
>
> (cheap-macro (list 0 1 2))
>
> or
>
> (cheap-macro '(0 1 2))
>
> into
>
> '(1 2 3)

How much generality do you want ? Do you want something like
(cheap-macro (append (list 1 2) (list 3 4)))

to also work ? If you want this much generality , I don't see how you can
avoid EVAL .If on the other hand you only want cheap-macro to work with
a list argument and all the elements of the list will be constant numbers
then writing (cheap-macro (list 0 1 2)) or (cheap-macro '(0 1 2))
is redundant , all you really need is (cheap-macro (0 1 2)) .In that case

(defmacro cheap-macro (&rest list)
(append (list 'quote) (mapcar (function expensive-defun) list)))

and

(defun frequently-run-defun-macro (number)
(case number
(1 (cheap-macro (0 1 2)))
(2 (cheap-macro (1 2 3)))
(3 (cheap-macro (2 3 4)))))

do the job.

> and then have
>
> (defun frequently-run-defun-macro (number)
> (case number
> (1 (cheap-macro (list 0 1 2)))
> (2 (cheap-macro (list 1 2 3)))
> (3 (cheap-macro (list 2 3 4)))))
>
> which gives me more intuitively readable AND faster running code,
> so the best of both worlds.
>
> I tried (more poking around in the dark) various combinations of quotes,
> backquotes and commas, but failed miserably. What did work was
>
> (defmacro cheap-macro (list)
> `(quote ,(eval `(mapcar #'1+ ,list))))
>
> but I cannot belief that I will have to fall back to eval for such a
> trivial macro. It is much more likely that I am still lacking
> understanding.
>
> What would be the "best-practice" way to implement this macro?

By the way , expensive-defun suggests to me that executing the DEFUN form
will be expensive whereas what you really mean is that the function will
be expensive. So expensive-function is a more suggestive name IMO.

--
vlaho.ninja/prog

Re: First own macro: How evil is eval?

<20211129084702.20@kylheku.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=16721&group=comp.lang.lisp#16721

  copy link   Newsgroups: comp.lang.lisp
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: 480-992-1380@kylheku.com (Kaz Kylheku)
Newsgroups: comp.lang.lisp
Subject: Re: First own macro: How evil is eval?
Date: Mon, 29 Nov 2021 17:23:45 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 107
Message-ID: <20211129084702.20@kylheku.com>
References: <m2h7bvc3rs.fsf@axel-reichert.de>
Injection-Date: Mon, 29 Nov 2021 17:23:45 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="660037e81636f526ccc9913bc021ec1b";
logging-data="29960"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX194sLqq12ErxHUMUbAkpqEYFeEj+VGovig="
User-Agent: slrn/1.0.3 (Linux)
Cancel-Lock: sha1:xZT4JMRzvi2s7Zp2u9odmK2RyXY=
 by: Kaz Kylheku - Mon, 29 Nov 2021 17:23 UTC

On 2021-11-28, Axel Reichert <mail@axel-reichert.de> wrote:
> What would be the "best-practice" way to implement this macro?

One way would be:

> (defun frequently-run-defun (number)
> (case number
> (1 (load-time-value (expensive-defun (list 0 1 2))))
> (2 (load-time-value (expensive-defun (list 1 2 3))))
> (3 (load-time-value (expensive-defun (list 2 3 4))))))

When this code is compiled, the compiler arranges for the expensive
calculations to be run one time when the compiled code is loaded.

The load-time values then become de facto literal objects that
are just retrieved whenever the expression's value is needed.

There is some eval in there somewhere under the hood; we just hid
it.

If you want to write a macro which takes a piece of syntax as an
argument (the usual habit of a macro) and converts the value of
that syntax to a literal, you cannot avoid eval.

That evaluation is not taking place in the usual time that macros
normally arrange: the evaluation time of the generated code.

When you let things evaluate in their usual time, then eval is
invisible. When you need unusual evaluation, then unless there
is an existing gadget for doing that (e.g. load-time-value if
you want load-time evaluation), then you will end up coding an eval
somewhere.

In the TXR Lisp language, I provided a built-in operator called
macro-time. If you write (macro-time E), E gets evaluated in the
top-level environment, to obtain a value V, and then (quote V) is the
result. Thus, you don't have to use eval. For some reason, I designated
this as a special operator. It is actually implemented right inside the
macro expander as a special case, though it could have been a macro.

In any case, the implementation of macro-time cheerfully calls eval.

Macros themselves are based on eval. Think about it; the Lisp
interpreter or compiler is scanning your code to expand macros. It sees
(mac 1 2 3). What does it do? It invokes the mac macro expander
function. But that is evaluation! The mac function contains expressions:
expressions that give the default values of optional and keyword
parameters, and expressions that make up its body. These (at least in
an abstract sense) are evaluated by eval. The (mac 1 2 3) call is
effectively evaled, and replaced with the result.

You just don't see explicit uses of the eval functions if you stick
to invoking evaluation in all the situations that the language
designers designed for you.

"evil eval" really just refers to going off the beaten path,
according to someone's opionion of what that is.

E.g. I designed macro-time for you in a certain non-CL dialect; so if
you are in that dialect and use macro-time, you are not perpetrating any
use of eval.

If you're in a dialet that doesn't have macro time, you have to write
your own, which involves eval, and so then you are raising eyebrows.

However, until this point in the article, I have been lying about
something, and it's time to come clean.

There is a way of writing macro-time in Common Lisp without using eval.
You can disguise eval by stashing an expression into the body of a
macrolet (local macro), and the macrolet can be generated by a macro:

(defmacro macro-time (expr)
(let ((secret-mac (gensym)))
`(macrolet ((,secret-mac () `(quote ,,expr)))
(,secret-mac))))

This works because invocation of macros is evaluation (IOEMIE?)

What is this doing? When we make a call such as

(macro-time (read-contents-of-file-as-string "/etc/shadow"))

first the macro-time macro is invoked. It calls (gensym) to allocate a
unique symbol G and binds that to secret-mac. Then it generates this
code:

(macrolet ((G () `(quote ,(read-contents-of-file-as-string "/etc/shadow"))))
(G))

This code replaces the (macro-time ...) invocation. So now the expander
is processing a macrolet. It establishes the definition of the local
macro G and processes the (G) form which tells it to call that macro.

The macro is called and so the `(quote ...) backquote expression is
evaluated: THERE IS OUR HIDDEN EVAL.

Summary: we got an expression to evaluate at macro-expansion time by
inserting it into the body of a locally defined macro, and throwing the
invocation of that macro into the path of the macro-expander.

P.S. there is no funtion read-contents-of-file-as-string, but you
can easily write one.

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

Re: First own macro: How evil is eval?

<expandafter-20211129201725@ram.dialup.fu-berlin.de>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=16722&group=comp.lang.lisp#16722

  copy link   Newsgroups: comp.lang.lisp
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!news.szaf.org!fu-berlin.de!uni-berlin.de!not-for-mail
From: ram@zedat.fu-berlin.de (Stefan Ram)
Newsgroups: comp.lang.lisp
Subject: Re: First own macro: How evil is eval?
Date: 29 Nov 2021 19:20:20 GMT
Organization: Stefan Ram
Lines: 38
Expires: 1 Mar 2022 11:59:58 GMT
Message-ID: <expandafter-20211129201725@ram.dialup.fu-berlin.de>
References: <m2h7bvc3rs.fsf@axel-reichert.de>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-Trace: news.uni-berlin.de jAWskL9ghcl58U2qp71+uAnDUrcHE0ptLHrz8KGFNMKjEY
X-Copyright: (C) Copyright 2021 Stefan Ram. All rights reserved.
Distribution through any means other than regular usenet
channels is forbidden. It is forbidden to publish this
article in the Web, to change URIs of this article into links,
and to transfer the body without this notice, but quotations
of parts in other Usenet posts are allowed.
X-No-Archive: Yes
Archive: no
X-No-Archive-Readme: "X-No-Archive" is set, because this prevents some
services to mirror the article in the web. But the article may
be kept on a Usenet archive server with only NNTP access.
X-No-Html: yes
Content-Language: en-US
Accept-Language: de-DE, en-US, it, fr-FR
 by: Stefan Ram - Mon, 29 Nov 2021 19:20 UTC

Axel Reichert <mail@axel-reichert.de> writes:
>(1 (expensive-defun (list 0 1 2)))

In TeX, one can use \expandafter to add another
level of makro expansion to a function definition.

\def\a{abc}
\def\x{\a}
\expandafter\def\expandafter\y\expandafter{\a}
\show\x
\show\y
\end

. The definition of "\y" in
"\expandafter\def\expandafter\y\expandafter{\a}" is similar
to the definition of "\x" in "\def\x{\a}", but when TeX
encounters the first "\expandafter", it follows it (skipping
the next token) just to find the next "\expandafter", it
then follows this to find the next "\expandafter", it then
follows this to find "\a". It will then expand "\a" giving
"abc". So, now it resumes after the first "\expandafter" to
process "\def\y{abc}". So the output with "\show" is:

> \x=macro:
->\a .
l.4 \show\x

?
> \y=macro:
->abc.
l.5 \show\y

?

.

Re: First own macro: How evil is eval?

<m2czmi3g86.fsf@axel-reichert.de>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=16723&group=comp.lang.lisp#16723

  copy link   Newsgroups: comp.lang.lisp
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: mail@axel-reichert.de (Axel Reichert)
Newsgroups: comp.lang.lisp
Subject: Re: First own macro: How evil is eval?
Date: Mon, 29 Nov 2021 20:38:01 +0100
Organization: A noiseless patient Spider
Lines: 43
Message-ID: <m2czmi3g86.fsf@axel-reichert.de>
References: <m2h7bvc3rs.fsf@axel-reichert.de> <8oTDiWCWd=lP89b5e@bongo-ra.co>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="52bd50aa3c0712be2ac1656b58095dd0";
logging-data="18914"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+WxfWbLGqenXYBkICZJBreg9oFCCkErsM="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (darwin)
Cancel-Lock: sha1:kE3VaMgzyfbB0TK5VAYZrdW0FCY=
sha1:Ksu8BDNmVJgti0JdRJcSf/P8Ya0=
 by: Axel Reichert - Mon, 29 Nov 2021 19:38 UTC

Spiros Bousbouras <spibou@gmail.com> writes:

> If on the other hand you only want cheap-macro to work with a list
> argument and all the elements of the list will be constant numbers

Yes.

> then writing (cheap-macro (list 0 1 2)) or (cheap-macro '(0 1 2)) is
> redundant , all you really need is (cheap-macro (0 1 2)) .

That was the point I was crucially missing, you made my day, many
thanks!

Because of this misconception one of my tries, the rather "canonical"

(defmacro cheap-macro (list)
`(mapcar #'1+ ,list))

was dismissed by me to early: Since, say,

(cheap-macro (list 1 2 3))

evaluated to

(2 3 4)

I thought this to be not enough and tried hard to somehow put a quote in
front of this. Had I tried this macro "downstream" I would have seen
that it does the job.

Hopefully I will become more confident with the quoting business further
down the macro road ...

> By the way , expensive-defun suggests to me that executing the DEFUN
> form will be expensive whereas what you really mean is that the
> function will be expensive. So expensive-function is a more suggestive
> name IMO.

Yes, you are right.

Thanks again!

Axel

Re: First own macro: How evil is eval?

<m28rx63fr3.fsf@axel-reichert.de>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=16724&group=comp.lang.lisp#16724

  copy link   Newsgroups: comp.lang.lisp
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: mail@axel-reichert.de (Axel Reichert)
Newsgroups: comp.lang.lisp
Subject: Re: First own macro: How evil is eval?
Date: Mon, 29 Nov 2021 20:48:16 +0100
Organization: A noiseless patient Spider
Lines: 45
Message-ID: <m28rx63fr3.fsf@axel-reichert.de>
References: <m2h7bvc3rs.fsf@axel-reichert.de> <20211129084702.20@kylheku.com>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="52bd50aa3c0712be2ac1656b58095dd0";
logging-data="18914"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+DWRD5iVjKOl4/m1+3HRYgCN2wdo/beqU="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (darwin)
Cancel-Lock: sha1:aSsM7mohsPLtZNtErcUZBRVC3MQ=
sha1:eIC0kxK/RkohblX8HHdTegtADVs=
 by: Axel Reichert - Mon, 29 Nov 2021 19:48 UTC

Kaz Kylheku <480-992-1380@kylheku.com> writes:

> One way would be:
>
>> (defun frequently-run-defun (number)
>> (case number
>> (1 (load-time-value (expensive-defun (list 0 1 2))))
>> (2 (load-time-value (expensive-defun (list 1 2 3))))
>> (3 (load-time-value (expensive-defun (list 2 3 4))))))
>
> When this code is compiled, the compiler arranges for the expensive
> calculations to be run one time when the compiled code is loaded.
>
> The load-time values then become de facto literal objects that
> are just retrieved whenever the expression's value is needed.

All this reads similar to compiler macros (I found them in Edmund
Weitz's "Common Lisp Recipes", tried them, but also screwed up).

> When you need unusual evaluation, then unless there is an existing
> gadget for doing that (e.g. load-time-value if you want load-time
> evaluation), then you will end up coding an eval somewhere.

[...]

> You just don't see explicit uses of the eval functions if you stick
> to invoking evaluation in all the situations that the language
> designers designed for you.

Great explanations, thank you.

> "evil eval" really just refers to going off the beaten path

Well, my instinct was that almost certainly I do not have to leave the
beaten path for "my first macro" (apart from mimicking textbook
examples), something that seemed like a trivial exercise.

> there is no funtion read-contents-of-file-as-string, but you can
> easily write one.

Or use one provided by various utility packages.

Best regards

Axel

Re: First own macro: How evil is eval?

<m24k7u3fij.fsf@axel-reichert.de>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=16725&group=comp.lang.lisp#16725

  copy link   Newsgroups: comp.lang.lisp
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: mail@axel-reichert.de (Axel Reichert)
Newsgroups: comp.lang.lisp
Subject: Re: First own macro: How evil is eval?
Date: Mon, 29 Nov 2021 20:53:24 +0100
Organization: A noiseless patient Spider
Lines: 13
Message-ID: <m24k7u3fij.fsf@axel-reichert.de>
References: <m2h7bvc3rs.fsf@axel-reichert.de>
<expandafter-20211129201725@ram.dialup.fu-berlin.de>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="52bd50aa3c0712be2ac1656b58095dd0";
logging-data="18914"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19KqNHDF4EQn6ObqAgOshWsbf/1ejyB6iI="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (darwin)
Cancel-Lock: sha1:NwtTx1wiZehsfaX0SmJYwMvPeHg=
sha1:gyDNFTtIAZOyl1yRI59nWwCT4zw=
 by: Axel Reichert - Mon, 29 Nov 2021 19:53 UTC

ram@zedat.fu-berlin.de (Stefan Ram) writes:

> In TeX, one can use \expandafter to add another level of makro
> expansion to a function definition.

While I have written several (La)TeX packages, at that time I did not
have any Lisp knowledge. This is quite an interesting tangent, since
back then much of the (plain) TeX macro business sounded like Greek to
me. Probably it will be rewarding to resurrect some layers of fossil
knowledge in my brain, even though it will not solve my problem at
hand. Anyway, much appreciated!

Axel

Re: First own macro: How evil is eval?

<m2zgpm1uk5.fsf@axel-reichert.de>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=16727&group=comp.lang.lisp#16727

  copy link   Newsgroups: comp.lang.lisp
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: mail@axel-reichert.de (Axel Reichert)
Newsgroups: comp.lang.lisp
Subject: Re: First own macro: How evil is eval?
Date: Mon, 29 Nov 2021 23:11:22 +0100
Organization: A noiseless patient Spider
Lines: 51
Message-ID: <m2zgpm1uk5.fsf@axel-reichert.de>
References: <m2h7bvc3rs.fsf@axel-reichert.de> <8oTDiWCWd=lP89b5e@bongo-ra.co>
<m2czmi3g86.fsf@axel-reichert.de>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="52bd50aa3c0712be2ac1656b58095dd0";
logging-data="21086"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/nX+6YVKhGYuJbtTPND2BhAs8dxoLXhOM="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (darwin)
Cancel-Lock: sha1:zHuwJTffDuxsck9xvlxkGJxTCsU=
sha1:C5T23qegrYH7Y11MzJUSqwEvPCE=
 by: Axel Reichert - Mon, 29 Nov 2021 22:11 UTC

Axel Reichert <mail@axel-reichert.de> writes:

> Spiros Bousbouras <spibou@gmail.com> writes:
>
>> If on the other hand you only want cheap-macro to work with a list
>> argument and all the elements of the list will be constant numbers
>
> Yes.
>
>> then writing (cheap-macro (list 0 1 2)) or (cheap-macro '(0 1 2)) is
>> redundant , all you really need is (cheap-macro (0 1 2)) .
>
> That was the point I was crucially missing, you made my day, many
> thanks!
>
> Because of this misconception one of my tries, the rather "canonical"
>
> (defmacro cheap-macro (list)
> `(mapcar #'1+ ,list))
>
> was dismissed by me to early: Since, say,
>
> (cheap-macro (list 1 2 3))
>
> evaluated to
>
> (2 3 4)
>
> I thought this to be not enough and tried hard to somehow put a quote in
> front of this. Had I tried this macro "downstream" I would have seen
> that it does the job.

Of course, my defmacro above does not the job, but rather mimics a
defun. While the result of the evaluation is fine, I was interested in
getting the same result after macro expansion. I still have to learn a
lot.

But your hint with append, quote etc. was helpful. By now I have a
working solution with

(defmacro cheap-macro (&rest args)
(append (list 'quote)
(list (expensive-function args))))

that is called by

(cheap-macro 1 2 3)

, so I got rid of the list argument along the way.

Axel

Re: First own macro: How evil is eval?

<20211130010121.219@kylheku.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=16728&group=comp.lang.lisp#16728

  copy link   Newsgroups: comp.lang.lisp
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: 480-992-1380@kylheku.com (Kaz Kylheku)
Newsgroups: comp.lang.lisp
Subject: Re: First own macro: How evil is eval?
Date: Tue, 30 Nov 2021 17:08:59 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 51
Message-ID: <20211130010121.219@kylheku.com>
References: <m2h7bvc3rs.fsf@axel-reichert.de>
<expandafter-20211129201725@ram.dialup.fu-berlin.de>
Injection-Date: Tue, 30 Nov 2021 17:08:59 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="9ee16b5229fb530a47dcfcff595d5844";
logging-data="21479"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+/t8uzZt87AA2ymEmgOqivKEMJhtEZaEw="
User-Agent: slrn/1.0.3 (Linux)
Cancel-Lock: sha1:VqG1Cg5n575udjR/Fo/ZoqADGOY=
 by: Kaz Kylheku - Tue, 30 Nov 2021 17:08 UTC

On 2021-11-29, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
> Axel Reichert <mail@axel-reichert.de> writes:
>>(1 (expensive-defun (list 0 1 2)))
>
> In TeX, one can use \expandafter to add another
> level of makro expansion to a function definition.
>
> \def\a{abc}
> \def\x{\a}
> \expandafter\def\expandafter\y\expandafter{\a}
> \show\x
> \show\y
> \end

This just looks like macro bodies are implicitly
quasiquoted, and expandafter is a kind of unquote operator
which can be invoked in the middle of such a body.

(define-symbol-macro a `"abc")

(define-symbol-macro x `a)

(define-symbol-macro y `,a)

x -> a
y -> "abc"

Or, well, not exactly.

It's like \expandafter is a control sequence that has a state
machine hidden behind it? It is called three times, to collect three
arguments, and when it has all three, it then acts on them to evoke the
semantics.

\expandafter \def \expandafter \ident \expandafter {body}

The quote protection is removed from body allowing its
expansion to be combined with the collected \def\ident.

(defmacro expandafter (defop ident expr)
`(,defop ,ident ,(eval expr)))

(define-symbol-macro a `"abc")

(define-symbol-macro x 'a)

(expandafter define-symbol-macro y 'a)

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

Re: First own macro: How evil is eval?

<edef-20211130184302@ram.dialup.fu-berlin.de>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=16729&group=comp.lang.lisp#16729

  copy link   Newsgroups: comp.lang.lisp
Path: i2pn2.org!i2pn.org!news.swapon.de!fu-berlin.de!uni-berlin.de!not-for-mail
From: ram@zedat.fu-berlin.de (Stefan Ram)
Newsgroups: comp.lang.lisp
Subject: Re: First own macro: How evil is eval?
Date: 30 Nov 2021 17:51:21 GMT
Organization: Stefan Ram
Lines: 88
Expires: 1 Mar 2022 11:59:58 GMT
Message-ID: <edef-20211130184302@ram.dialup.fu-berlin.de>
References: <m2h7bvc3rs.fsf@axel-reichert.de> <expandafter-20211129201725@ram.dialup.fu-berlin.de> <20211130010121.219@kylheku.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-Trace: news.uni-berlin.de vMOQkqUUQxnY2p4khwnGVgHYFomQaI3YVCdMjtFlhFwQkK
X-Copyright: (C) Copyright 2021 Stefan Ram. All rights reserved.
Distribution through any means other than regular usenet
channels is forbidden. It is forbidden to publish this
article in the Web, to change URIs of this article into links,
and to transfer the body without this notice, but quotations
of parts in other Usenet posts are allowed.
X-No-Archive: Yes
Archive: no
X-No-Archive-Readme: "X-No-Archive" is set, because this prevents some
services to mirror the article in the web. But the article may
be kept on a Usenet archive server with only NNTP access.
X-No-Html: yes
Content-Language: en-US
Accept-Language: de-DE, en-US, it, fr-FR
 by: Stefan Ram - Tue, 30 Nov 2021 17:51 UTC

Kaz Kylheku <480-992-1380@kylheku.com> writes:
>It's like \expandafter is a control sequence that has a state
>machine hidden behind it?

The first part of the behavior of "\expandafter" is on a low
level: The level of lexical tokens, not the level of
syntactical structures. It is not restricted just to
definitions, but can be used everywhere. (An example
for this is given in the appendix below.)

But my TeX skills were a bit rusty. In fact, what I
originally wanted to show is easier. There is an "\edef"
which will evaluated the body of the definition once before
the actual definition takes place. And one can use
"\noexpand" to prevent the expansion of the next token
("\a", below) within such a body, so:

\def\a{abc}
\def\x{\a}
\edef\y{\a}
\edef\z{\noexpand\a}
\show\x
\show\y
\show\z
\end

outputs:

This is TeX ...
(./main.tex
> \x=macro:
->\a .
l.5 \show\x

?
> \y=macro:
->abc.
l.6 \show\y

?
> \z=macro:
->\a .
l.7 \show\z

?
)

Appendix: Some details about "\expandafter" only for readers
who really want to know it in detail

\def\x{A}
\def\y{B}
\show\x
\expandafter\show\csname y\endcsname
\end

Above, TeX expands command after command. Two \defs and one
\show. Then it executes "\expandafter". "csname" builds
control sequences from tokens, so "\expandafter" expands
"\csname y\endcsname" into "\y". Then the "\show\y" is
executed, showing y.

One can iterate this, for example:

\expandafter\expandafter\expandafter\show\csname csname\endcsname y\endcsname

The first (and third) "\expandafter" yield

\expandafter\show\csname y\endcsname

which then yields

\show\y

which then is executed. From the documentation:

|\expandafter
| |TeX first reads the token that comes immediately after
|\expandafter, without expanding it; let's call this token t.
|Then TeX reads the token that comes after t (and possibly
|more tokens, if that token has an argument), replacing it by
|its expansion. Finally TeX puts t back in front of that
|expansion.

.


devel / comp.lang.lisp / First own macro: How evil is eval?

1
server_pubkey.txt

rocksolid light 0.9.81
clearnet tor