[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: How to create a higher order function?
From: |
Marcin Borkowski |
Subject: |
Re: How to create a higher order function? |
Date: |
Fri, 24 Sep 2021 10:57:53 +0200 |
User-agent: |
mu4e 1.1.0; emacs 28.0.50 |
On 2021-09-22, at 21:03, Stefan Monnier via Users list for the GNU Emacs text
editor <help-gnu-emacs@gnu.org> wrote:
> I think what you meant was
>
> (defun negate (fun)
> "Return a function returning the logical opposite of FUN."
> `(lambda (&rest args)
> (not (apply ',fun args))))
Interesting, I didn't think of this.
>> But maybe (B) is better under some circumstances?
>
> I'm hoping B can be banned at some point in the future ;-)
This is great news, since I read it "don't bother with it". :-)
>> Is it faster?
>
> I don't think so. Currently closures constructed in lexical-binding
> mode are not super efficient (back in Emacs-24, the focus was on
> providing lexical-scoping with clean semantics and without breaking or
> slowing down dynamic scoping. Efficiency of lexical-binding was
> secondary, and we haven't really attacked that yet).
>
> More specifically, constructing a closure will allocate two new vectors
> (whereas the ideal would be 1 vector), and one of them holds a lot more
> than the set of free variables (it also holds all the constants used in
> the code, such as the names of all the functions it calls).
>
> But the above construction of a (lambda ...) list to mimic a true
> closure isn't very efficient either: if I count correctly it will need
> to allocate 9 new cons cells.
>
> Which is currently faster, I don't know. But if the construction of the
> true closure is slower, at least there's the theoretical possibility to
> invest implementation efforts into making it more efficient by using
> a more conventional closure representation.
>
> As for efficiency when calling the constructed function, I'm pretty sure
> that C will be significantly faster (tho you'll have to call them many
> times to see the difference ;-), but I suspect that in practice for this
> specific example the difference may not be very large because most of
> the time will be spent processing the `&rest` (i.e. converting the args
> (stored in a vector) into a list) and the `apply` (i.e. converting the
> list back to a vector), and the benchmark will likely show that you're
> spending a lot of time in the GC (because of the need to recover all
> those temporary lists generated by the `&rest`).
>
> So to better see the effect you might want to use something like:
>
> (defun negate (fun)
> "Return a function returning the logical opposite of FUN."
> (lambda (arg1 arg2)
> (not (funcall fun arg1 arg2))))
>
> where I'd expect the (C) version to be faster by a quite
> significant margin (like more than a factor 2).
Thanks for your detailed answer! As usual, it turns out that there's
always so much to learn!
Best,
--
Marcin Borkowski
http://mbork.pl
- Re: [External] : How to create a higher order function?, (continued)
- Re: [External] : How to create a higher order function?, Emanuel Berg, 2021/09/24
- RE: [External] : How to create a higher order function?, Drew Adams, 2021/09/24
- Re: [External] : How to create a higher order function?, Emanuel Berg, 2021/09/24
- Re: [External] : How to create a higher order function?, Marcin Borkowski, 2021/09/25
- Re: [External] : How to create a higher order function?, Emanuel Berg, 2021/09/25
- Re: [External] : How to create a higher order function?, Marcin Borkowski, 2021/09/27
- Re: [External] : How to create a higher order function?, Emanuel Berg, 2021/09/27
Re: How to create a higher order function?, Stefan Monnier, 2021/09/22