* more url-utils? @ 2011-05-14 10:32 joakim 2011-05-14 11:21 ` Lars Magne Ingebrigtsen ` (2 more replies) 0 siblings, 3 replies; 93+ messages in thread From: joakim @ 2011-05-14 10:32 UTC (permalink / raw) To: emacs-devel I feel the url functions have become really useful with the addition of the xml parser and shr, but we can do better still. Would the defun below be suitable to include in url-util? You nearly always want to work with the data part of the document. The code snippet below occurs a lot in different packages. A wrapper that downloads a file(like curl or wget) would be nice also. (defun org-feed-skip-http-headers (buffer) "Remove HTTP headers from BUFFER, and return it. Assumes headers are indeed present!" (with-current-buffer buffer (widen) (goto-char (point-min)) (search-forward "\n\n") (delete-region (point-min) (point)) buffer)) -- Joakim Verona ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-14 10:32 more url-utils? joakim @ 2011-05-14 11:21 ` Lars Magne Ingebrigtsen 2011-05-14 11:42 ` joakim ` (2 more replies) 2011-05-14 13:21 ` Ted Zlatanov 2011-05-15 13:34 ` Chong Yidong 2 siblings, 3 replies; 93+ messages in thread From: Lars Magne Ingebrigtsen @ 2011-05-14 11:21 UTC (permalink / raw) To: emacs-devel joakim@verona.se writes: > Would the defun below be suitable to include in url-util? > You nearly always want to work with the data part of the document. Perhaps binding something like `url-return-data-only', and then having url-retrieve strip the headers before returning the buffer would be nice. My guess is that more than 90% of the users of `url-retrieve' don't care about the headers, so having it do the stripping would be convenient. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog http://lars.ingebrigtsen.no/ ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-14 11:21 ` Lars Magne Ingebrigtsen @ 2011-05-14 11:42 ` joakim 2011-05-15 1:59 ` Lars Magne Ingebrigtsen 2011-05-14 20:42 ` Dimitri Fontaine 2011-05-15 14:26 ` Jason Rumney 2 siblings, 1 reply; 93+ messages in thread From: joakim @ 2011-05-14 11:42 UTC (permalink / raw) To: emacs-devel Lars Magne Ingebrigtsen <larsi@gnus.org> writes: > joakim@verona.se writes: > >> Would the defun below be suitable to include in url-util? >> You nearly always want to work with the data part of the document. > > Perhaps binding something like `url-return-data-only', and then having > url-retrieve strip the headers before returning the buffer would be > nice. > > My guess is that more than 90% of the users of `url-retrieve' don't care > about the headers, so having it do the stripping would be convenient. Yes, normaly you only want the data, and an exception if that doesnt happen properly. So, your proposal is good. Except a function argument would expose the interface better IMHO. (But I understand why in practice a binding might be more feasible. Hmm.) -- Joakim Verona ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-14 11:42 ` joakim @ 2011-05-15 1:59 ` Lars Magne Ingebrigtsen 0 siblings, 0 replies; 93+ messages in thread From: Lars Magne Ingebrigtsen @ 2011-05-15 1:59 UTC (permalink / raw) To: emacs-devel joakim@verona.se writes: > Yes, normaly you only want the data, and an exception if that doesnt > happen properly. So, your proposal is good. Except a function argument > would expose the interface better IMHO. (But I understand why in > practice a binding might be more feasible. Hmm.) For backwards compatibility (i.e., for out-of-bzr users) a binding might be preferable (perhaps), but you're right, an extra optional parameter `data-only-p' would make more sense. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog http://lars.ingebrigtsen.no/ ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-14 11:21 ` Lars Magne Ingebrigtsen 2011-05-14 11:42 ` joakim @ 2011-05-14 20:42 ` Dimitri Fontaine 2011-05-15 14:26 ` Jason Rumney 2 siblings, 0 replies; 93+ messages in thread From: Dimitri Fontaine @ 2011-05-14 20:42 UTC (permalink / raw) To: emacs-devel Lars Magne Ingebrigtsen <larsi@gnus.org> writes: > My guess is that more than 90% of the users of `url-retrieve' don't care > about the headers, so having it do the stripping would be convenient. Right. As a user of it, I concur. Now maybe a new function url-delete-headers would be good enough. It would do the delete in current-buffer, and avoid code that currently looks like that: ;; prune HTTP headers before save (goto-char (point-min)) (re-search-forward "^$" nil 'move) (forward-char) (delete-region (point-min) (point)) Regards, -- dim ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-14 11:21 ` Lars Magne Ingebrigtsen 2011-05-14 11:42 ` joakim 2011-05-14 20:42 ` Dimitri Fontaine @ 2011-05-15 14:26 ` Jason Rumney 2011-05-16 18:25 ` Ted Zlatanov 2 siblings, 1 reply; 93+ messages in thread From: Jason Rumney @ 2011-05-15 14:26 UTC (permalink / raw) To: emacs-devel Lars Magne Ingebrigtsen <larsi@gnus.org> writes: > joakim@verona.se writes: > >> Would the defun below be suitable to include in url-util? >> You nearly always want to work with the data part of the document. > > Perhaps binding something like `url-return-data-only', and then having > url-retrieve strip the headers before returning the buffer would be > nice. It would be even nicer if the headers were parsed into a buffer local alist. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-15 14:26 ` Jason Rumney @ 2011-05-16 18:25 ` Ted Zlatanov 2011-05-16 19:03 ` Stefan Monnier 0 siblings, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-16 18:25 UTC (permalink / raw) To: emacs-devel On Sun, 15 May 2011 22:26:13 +0800 Jason Rumney <jasonr@gnu.org> wrote: JR> It would be even nicer if the headers were parsed into a buffer JR> local alist. Yes, definitely. That should be done by default regardless of the other improvements discussed here. On Mon, 16 May 2011 12:45:03 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: SM> On Mon, 16 May 2011 09:19:18 -0600 Tom Tromey <tromey@redhat.com> wrote: Tom> IIRC, in package.el I had to special-case some URL types, because Tom> headers are inconsistently used. E.g., I think the 'ftp' method won't Tom> leave headers in the buffer. It would be nice if this bit were handled Tom> by the url package rather than all the callers. SM> Sounds like an inconsistency that needs fixing, indeed. You might want SM> to make a bug-report for it. I had problems using a file:// URL with package.el, which made local testing a pain. The problem was exactly with the missing headers, same as the ftp:// URLs. So I'll second the bug report if Tom opens it, or open a new one. On Sun, 15 May 2011 03:59:52 +0200 Lars Magne Ingebrigtsen <larsi@gnus.org> wrote: LMI> For backwards compatibility (i.e., for out-of-bzr users) a binding might LMI> be preferable (perhaps), but you're right, an extra optional parameter LMI> `data-only-p' would make more sense. After looking at many examples in Emacs, I can't find or think of any need for the headers *as text* in the code I've seen. I would: 1) rename the function, obsolete the old one, turn headers off by default in the new version, and hunt down all the cases where code removes them from the content. Yes it's a pain. 2) find any real need for the headers as *text* (I found none). If none is found, just do the buffer-local alist Jason suggested, and maybe provide all the headers as a single text string in case someone needs them. I realize this is more invasive but backwards compatibility means lots of unnecessary code to remove the headers will keep being written. I volunteer to do both tasks above. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 18:25 ` Ted Zlatanov @ 2011-05-16 19:03 ` Stefan Monnier 2011-05-16 19:17 ` Ted Zlatanov 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2011-05-16 19:03 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel > After looking at many examples in Emacs, I can't find or think of any > need for the headers *as text* in the code I've seen. I would: That sounds right. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 19:03 ` Stefan Monnier @ 2011-05-16 19:17 ` Ted Zlatanov 2011-05-16 19:22 ` Lennart Borgman 2011-05-16 19:53 ` Stefan Monnier 0 siblings, 2 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-16 19:17 UTC (permalink / raw) To: emacs-devel On Mon, 16 May 2011 16:03:19 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> After looking at many examples in Emacs, I can't find or think of any >> need for the headers *as text* in the code I've seen. I would: SM> That sounds right. ...so can I go ahead with my proposal or would you rather be conservative and keep the old behavior, making API users turn off headers explicitly? Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 19:17 ` Ted Zlatanov @ 2011-05-16 19:22 ` Lennart Borgman 2011-05-16 19:32 ` Ted Zlatanov 2011-05-16 19:53 ` Stefan Monnier 1 sibling, 1 reply; 93+ messages in thread From: Lennart Borgman @ 2011-05-16 19:22 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel 2011/5/16 Ted Zlatanov <tzz@lifelogs.com>: > On Mon, 16 May 2011 16:03:19 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: > >>> After looking at many examples in Emacs, I can't find or think of any >>> need for the headers *as text* in the code I've seen. I would: > > SM> That sounds right. > > ...so can I go ahead with my proposal or would you rather be > conservative and keep the old behavior, making API users turn off > headers explicitly? I would go for Julien's suggestion with a function `url-remove-headers' which also parsed the headers and returned a alist of the headers. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 19:22 ` Lennart Borgman @ 2011-05-16 19:32 ` Ted Zlatanov 2011-05-16 19:33 ` Lennart Borgman 2011-05-16 19:52 ` Julien Danjou 0 siblings, 2 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-16 19:32 UTC (permalink / raw) To: emacs-devel On Mon, 16 May 2011 21:22:02 +0200 Lennart Borgman <lennart.borgman@gmail.com> wrote: LB> 2011/5/16 Ted Zlatanov <tzz@lifelogs.com>: >> On Mon, 16 May 2011 16:03:19 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> >>>> After looking at many examples in Emacs, I can't find or think of any >>>> need for the headers *as text* in the code I've seen. I would: >> SM> That sounds right. >> >> ...so can I go ahead with my proposal or would you rather be >> conservative and keep the old behavior, making API users turn off >> headers explicitly? LB> I would go for Julien's suggestion with a function LB> `url-remove-headers' which also parsed the headers and returned a LB> alist of the headers. I'm trying to avoid that approach: we just established the headers are almost never necessary in the buffer. So we should not ask the API users to do anything extra to remove them. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 19:32 ` Ted Zlatanov @ 2011-05-16 19:33 ` Lennart Borgman 2011-05-16 19:55 ` Ted Zlatanov 2011-05-16 19:52 ` Julien Danjou 1 sibling, 1 reply; 93+ messages in thread From: Lennart Borgman @ 2011-05-16 19:33 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel 2011/5/16 Ted Zlatanov <tzz@lifelogs.com>: > On Mon, 16 May 2011 21:22:02 +0200 Lennart Borgman <lennart.borgman@gmail.com> wrote: > > LB> 2011/5/16 Ted Zlatanov <tzz@lifelogs.com>: >>> On Mon, 16 May 2011 16:03:19 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >>> >>>>> After looking at many examples in Emacs, I can't find or think of any >>>>> need for the headers *as text* in the code I've seen. I would: >>> > SM> That sounds right. >>> >>> ...so can I go ahead with my proposal or would you rather be >>> conservative and keep the old behavior, making API users turn off >>> headers explicitly? > > LB> I would go for Julien's suggestion with a function > LB> `url-remove-headers' which also parsed the headers and returned a > LB> alist of the headers. > > I'm trying to avoid that approach: we just established the headers are > almost never necessary in the buffer. So we should not ask the API > users to do anything extra to remove them. It can be combined with your approach with an extra argument. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 19:33 ` Lennart Borgman @ 2011-05-16 19:55 ` Ted Zlatanov 0 siblings, 0 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-16 19:55 UTC (permalink / raw) To: emacs-devel On Mon, 16 May 2011 21:33:55 +0200 Lennart Borgman <lennart.borgman@gmail.com> wrote: LB> 2011/5/16 Ted Zlatanov <tzz@lifelogs.com>: >> On Mon, 16 May 2011 21:22:02 +0200 Lennart Borgman <lennart.borgman@gmail.com> wrote: LB> I would go for Julien's suggestion with a function LB> `url-remove-headers' which also parsed the headers and returned a LB> alist of the headers. >> >> I'm trying to avoid that approach: we just established the headers are >> almost never necessary in the buffer. So we should not ask the API >> users to do anything extra to remove them. LB> It can be combined with your approach with an extra argument. The existence of `url-remove-headers' is a symptom of a bad API and should be unnecessary, together with extra arguments. The usage would be (remember, `url-retrieve-synchronously' is obsoleted in my proposal in favor or `url-retrieve2-synchronously'): (if (setq buf (url-retrieve2-synchronously url)) (with-current-buffer buf (message "Header x is %s" (assq 'x url-headers-alist)) (message "Header y is %s" (assoc "y" url-headers-alist)) (message "The headers as a string are %s" url-headers-as-string) (message "data is %s" (buffer-string)) ...) (...handle errors here...)) which is, I think, how everyone wants to use this function based on browsing a whole bunch of code. So inserting the headers would be just (insert url-headers-as-string) and too trivial to provide as a function. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 19:32 ` Ted Zlatanov 2011-05-16 19:33 ` Lennart Borgman @ 2011-05-16 19:52 ` Julien Danjou 2011-05-16 20:18 ` Ted Zlatanov 1 sibling, 1 reply; 93+ messages in thread From: Julien Danjou @ 2011-05-16 19:52 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel [-- Attachment #1: Type: text/plain, Size: 903 bytes --] On Mon, May 16 2011, Ted Zlatanov wrote: > I'm trying to avoid that approach: we just established the headers are > almost never necessary in the buffer. So we should not ask the API > users to do anything extra to remove them. That can be true. When you fetch an URL, you want to know if the fetch result is a 200 OK or a 404 Not Found. That's the absolute minimum thing you want to do if you plan to write correct code. So just dropping the header sounds like a very bad programming practice, and not something I'd encourage. I wrote code with url.el. And what I always did is (search-forward "\n\n") to move point between headers and content, and then parse the headers to at least check the return code (expecting 200 usually). I often also needed the Content-Type (so clearly an alist of parsed headers would be welcome). -- Julien Danjou ❱ http://julien.danjou.info [-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --] ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 19:52 ` Julien Danjou @ 2011-05-16 20:18 ` Ted Zlatanov 2011-05-17 3:04 ` Stefan Monnier 2011-05-17 8:13 ` Julien Danjou 0 siblings, 2 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-16 20:18 UTC (permalink / raw) To: emacs-devel On Mon, 16 May 2011 21:52:43 +0200 Julien Danjou <julien@danjou.info> wrote: JD> On Mon, May 16 2011, Ted Zlatanov wrote: >> I'm trying to avoid that approach: we just established the headers are >> almost never necessary in the buffer. So we should not ask the API >> users to do anything extra to remove them. JD> That can be true. When you fetch an URL, you want to know if the fetch JD> result is a 200 OK or a 404 Not Found. That's the absolute minimum thing JD> you want to do if you plan to write correct code. JD> So just dropping the header sounds like a very bad programming practice, JD> and not something I'd encourage. You won't get a HTTP status (or any headers, sometimes) from a non-HTTP URL. So the status is only useful in some cases and relying on it makes the code inflexible, depending on the transport protocol's artifacts. JD> I wrote code with url.el. And what I always did is (search-forward JD> "\n\n") to move point between headers and content, and then parse the JD> headers to at least check the return code (expecting 200 usually). That's a symptom of a bad API that tied you to HTTP headers and what I was trying to eliminate. On Mon, 16 May 2011 16:53:37 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >>>> After looking at many examples in Emacs, I can't find or think of any >>>> need for the headers *as text* in the code I've seen. I would: SM> That sounds right. >> ...so can I go ahead with my proposal or would you rather be >> conservative and keep the old behavior, making API users turn off >> headers explicitly? SM> There are 3 parts. SM> - removal of header text. SM> - backward compatibility. SM> - providing header info in a non-textual format. Ah, OK. So my proposal does not fit because you want backwards compatibility. I was hoping to eliminate the bad API altogether but this is at least a step forward. Let me know if you want me to implement any parts of this. Thanks Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 20:18 ` Ted Zlatanov @ 2011-05-17 3:04 ` Stefan Monnier 2011-05-17 8:13 ` Julien Danjou 1 sibling, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2011-05-17 3:04 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel > Ah, OK. So my proposal does not fit because you want backwards > compatibility. I think that's right, although I'm not completely clear on what is exactly your proposal. > I was hoping to eliminate the bad API altogether but this is at least > a step forward. Let me know if you want me to implement any parts > of this. If you can provide a patch that give us a clean new API together with some backward compatibility layer, that would be great. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 20:18 ` Ted Zlatanov 2011-05-17 3:04 ` Stefan Monnier @ 2011-05-17 8:13 ` Julien Danjou 1 sibling, 0 replies; 93+ messages in thread From: Julien Danjou @ 2011-05-17 8:13 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel [-- Attachment #1: Type: text/plain, Size: 727 bytes --] On Mon, May 16 2011, Ted Zlatanov wrote: > That's a symptom of a bad API that tied you to HTTP headers and what I > was trying to eliminate. Indeed Ted, you're right. I was only thinking about HTTP, stupid I am. :) This probably means that the API should be changed (or should evolve by addition/deprecation at least) to return a buffer with data, but let access things like a status code (meaning something more general than HTTP code) and possibly extra data like the HTTP headers or whatever can be useful contextual information for the retrieved URL. I don't know every backend url.el supports, so I can't imagine what a good abstraction might be. :) -- Julien Danjou ❱ http://julien.danjou.info [-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --] ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 19:17 ` Ted Zlatanov 2011-05-16 19:22 ` Lennart Borgman @ 2011-05-16 19:53 ` Stefan Monnier 2011-05-16 21:07 ` joakim 2011-05-17 11:40 ` Lars Magne Ingebrigtsen 1 sibling, 2 replies; 93+ messages in thread From: Stefan Monnier @ 2011-05-16 19:53 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel >>> After looking at many examples in Emacs, I can't find or think of any >>> need for the headers *as text* in the code I've seen. I would: SM> That sounds right. > ...so can I go ahead with my proposal or would you rather be > conservative and keep the old behavior, making API users turn off > headers explicitly? There are 3 parts. - removal of header text. - backward compatibility. - providing header info in a non-textual format. All three are important. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 19:53 ` Stefan Monnier @ 2011-05-16 21:07 ` joakim 2011-05-16 21:18 ` Ted Zlatanov 2011-05-17 11:40 ` Lars Magne Ingebrigtsen 1 sibling, 1 reply; 93+ messages in thread From: joakim @ 2011-05-16 21:07 UTC (permalink / raw) To: Stefan Monnier; +Cc: Ted Zlatanov, emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >>>> After looking at many examples in Emacs, I can't find or think of any >>>> need for the headers *as text* in the code I've seen. I would: > SM> That sounds right. >> ...so can I go ahead with my proposal or would you rather be >> conservative and keep the old behavior, making API users turn off >> headers explicitly? > > There are 3 parts. > - removal of header text. > - backward compatibility. > - providing header info in a non-textual format. > > All three are important. Teds proposal addresses all three concerns right? - The new API does what coders expect, no information is lost - the old api is retained but marked obsolete - headers are accessible in alist format Its more work but Teds volunteered to do it. Great! > > Stefan -- Joakim Verona ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 21:07 ` joakim @ 2011-05-16 21:18 ` Ted Zlatanov 2011-05-16 21:21 ` Lennart Borgman 2011-05-16 21:58 ` joakim 0 siblings, 2 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-16 21:18 UTC (permalink / raw) To: emacs-devel On Mon, 16 May 2011 23:07:49 +0200 joakim@verona.se wrote: j> Stefan Monnier <monnier@iro.umontreal.ca> writes: >>>>> After looking at many examples in Emacs, I can't find or think of any >>>>> need for the headers *as text* in the code I've seen. I would: SM> That sounds right. >>> ...so can I go ahead with my proposal or would you rather be >>> conservative and keep the old behavior, making API users turn off >>> headers explicitly? >> >> There are 3 parts. >> - removal of header text. >> - backward compatibility. >> - providing header info in a non-textual format. >> >> All three are important. j> Teds proposal addresses all three concerns right? j> - The new API does what coders expect, no information is lost j> - the old api is retained but marked obsolete j> - headers are accessible in alist format j> Its more work but Teds volunteered to do it. Great! I don't think marking the old API obsolete will preserve backwards compatibility. But if Stefan thinks so, I'll do it according to my proposal. Otherwise he'll have to decide what the API will be. I don't mind the extra work if it improves Emacs. Right now using url-*.el to just get some data is pretty painful compared to Perl's LWP, for instance. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 21:18 ` Ted Zlatanov @ 2011-05-16 21:21 ` Lennart Borgman 2011-05-16 21:58 ` joakim 1 sibling, 0 replies; 93+ messages in thread From: Lennart Borgman @ 2011-05-16 21:21 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel 2011/5/16 Ted Zlatanov <tzz@lifelogs.com>: > On Mon, 16 May 2011 23:07:49 +0200 joakim@verona.se wrote: > > j> Stefan Monnier <monnier@iro.umontreal.ca> writes: >>>>>> After looking at many examples in Emacs, I can't find or think of any >>>>>> need for the headers *as text* in the code I've seen. I would: > SM> That sounds right. >>>> ...so can I go ahead with my proposal or would you rather be >>>> conservative and keep the old behavior, making API users turn off >>>> headers explicitly? >>> >>> There are 3 parts. >>> - removal of header text. >>> - backward compatibility. >>> - providing header info in a non-textual format. >>> >>> All three are important. > > j> Teds proposal addresses all three concerns right? > j> - The new API does what coders expect, no information is lost > j> - the old api is retained but marked obsolete > j> - headers are accessible in alist format > > j> Its more work but Teds volunteered to do it. Great! > > I don't think marking the old API obsolete will preserve backwards > compatibility. But if Stefan thinks so, I'll do it according to my > proposal. Otherwise he'll have to decide what the API will be. > > I don't mind the extra work if it improves Emacs. Right now using > url-*.el to just get some data is pretty painful compared to Perl's LWP, > for instance. Yes, it is pretty painful and hardly documented. Take for example url-http-parse-headers. Anyone can say what it does by just reading the doc string? Improvements will save a lot of time! ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 21:18 ` Ted Zlatanov 2011-05-16 21:21 ` Lennart Borgman @ 2011-05-16 21:58 ` joakim 1 sibling, 0 replies; 93+ messages in thread From: joakim @ 2011-05-16 21:58 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel Ted Zlatanov <tzz@lifelogs.com> writes: > On Mon, 16 May 2011 23:07:49 +0200 joakim@verona.se wrote: > > j> Stefan Monnier <monnier@iro.umontreal.ca> writes: >>>>>> After looking at many examples in Emacs, I can't find or think of any >>>>>> need for the headers *as text* in the code I've seen. I would: > SM> That sounds right. >>>> ...so can I go ahead with my proposal or would you rather be >>>> conservative and keep the old behavior, making API users turn off >>>> headers explicitly? >>> >>> There are 3 parts. >>> - removal of header text. >>> - backward compatibility. >>> - providing header info in a non-textual format. >>> >>> All three are important. > > j> Teds proposal addresses all three concerns right? > j> - The new API does what coders expect, no information is lost > j> - the old api is retained but marked obsolete > j> - headers are accessible in alist format > > j> Its more work but Teds volunteered to do it. Great! > > I don't think marking the old API obsolete will preserve backwards > compatibility. But if Stefan thinks so, I'll do it according to my > proposal. Otherwise he'll have to decide what the API will be. > > I don't mind the extra work if it improves Emacs. Right now using > url-*.el to just get some data is pretty painful compared to Perl's LWP, > for instance. True. We had a little inhouse "competition" comparing implementations of reading and parsing an internal REST datasource. My Emacs implementation was pretty lean compared with Android/Iphone implementations, but the Clojure implementation was five lines of code. Perls would be 5 characters I presume :) > > Ted > -- Joakim Verona ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 19:53 ` Stefan Monnier 2011-05-16 21:07 ` joakim @ 2011-05-17 11:40 ` Lars Magne Ingebrigtsen 2011-05-17 13:34 ` Stefan Monnier 1 sibling, 1 reply; 93+ messages in thread From: Lars Magne Ingebrigtsen @ 2011-05-17 11:40 UTC (permalink / raw) To: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: > There are 3 parts. > - removal of header text. > - backward compatibility. > - providing header info in a non-textual format. Adding a new optional parameter `no-headers' (or something) to `url-retrieve' (and -synchronous) could do the trick, but the caller (who wants no headers) have to do some pretty deep inspection to find out whether this version of `url-retrieve' has that parameter or not. So how about a new function, with a signature something like this: (defun url-fetch (url &keywords callback cbargs silent)) The `callback' is optional, and if not provided, makes `url-fetch' be synchronous. (Too bad Emacs doesn't really have a culture for closures, because then we could get rid of cbargs, too. Being able to say stuff like (defun save-url (file) (url-fetch url :callback (lambda (status) (write-region (point-min) (point-max) file)))) would be kinda elegant, I think, instead of (defun save-url (file) (url-fetch url :callback (lambda (status file) (write-region (point-min) (point-max) file)) :cbargs (list file))) But that's a different discussion, perhaps. :-) -- (domestic pets only, the antidote for overdose, milk.) bloggy blog http://lars.ingebrigtsen.no/ ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-17 11:40 ` Lars Magne Ingebrigtsen @ 2011-05-17 13:34 ` Stefan Monnier 0 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2011-05-17 13:34 UTC (permalink / raw) To: emacs-devel >> There are 3 parts. >> - removal of header text. >> - backward compatibility. >> - providing header info in a non-textual format. > Adding a new optional parameter `no-headers' (or something) to > `url-retrieve' (and -synchronous) could do the trick, but the caller > (who wants no headers) have to do some pretty deep inspection to find > out whether this version of `url-retrieve' has that parameter or not. Agreed. > So how about a new function, with a signature something like this: > (defun url-fetch (url &keywords callback cbargs silent)) Sounds about right. > The `callback' is optional, and if not provided, makes `url-fetch' be > synchronous. Yes, I used the same convention in mpc.el. > (Too bad Emacs doesn't really have a culture for closures, because > then we could get rid of cbargs, too. Being able to say stuff like This change to URL would be for Emacs-24 which does support closures natively (and I encourage people to use this facility), so we could definitely drop the `cbargs'. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-14 10:32 more url-utils? joakim 2011-05-14 11:21 ` Lars Magne Ingebrigtsen @ 2011-05-14 13:21 ` Ted Zlatanov 2011-05-16 13:15 ` Stefan Monnier 2011-05-15 13:34 ` Chong Yidong 2 siblings, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-14 13:21 UTC (permalink / raw) To: emacs-devel On Sat, 14 May 2011 12:32:55 +0200 joakim@verona.se wrote: j> Would the defun below be suitable to include in url-util? j> You nearly always want to work with the data part of the document. j> The code snippet below occurs a lot in different packages. j> A wrapper that downloads a file(like curl or wget) would be nice also. j> (defun org-feed-skip-http-headers (buffer) ... Yes to both, but like Lars I think the header-skipping should be an option for the current API and not a new function. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-14 13:21 ` Ted Zlatanov @ 2011-05-16 13:15 ` Stefan Monnier 2011-05-16 15:19 ` Tom Tromey 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2011-05-16 13:15 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel j> Would the defun below be suitable to include in url-util? j> You nearly always want to work with the data part of the document. j> The code snippet below occurs a lot in different packages. j> A wrapper that downloads a file(like curl or wget) would be nice also. j> (defun org-feed-skip-http-headers (buffer) > ... > Yes to both, but like Lars I think the header-skipping should be an > option for the current API and not a new function. While Emacs uses them a lot, dynamically-scoped variables used as implicit extra parameters are bad. In many cases, it's difficult to avoid using them, but in this case, calling a function after the url-retrieve call works just as well, so there's no excuse. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 13:15 ` Stefan Monnier @ 2011-05-16 15:19 ` Tom Tromey 2011-05-16 15:45 ` Stefan Monnier 2011-05-16 17:04 ` joakim 0 siblings, 2 replies; 93+ messages in thread From: Tom Tromey @ 2011-05-16 15:19 UTC (permalink / raw) To: Stefan Monnier; +Cc: Ted Zlatanov, emacs-devel >>>>> "Stefan" == Stefan Monnier <monnier@iro.umontreal.ca> writes: Stefan> While Emacs uses them a lot, dynamically-scoped variables used as Stefan> implicit extra parameters are bad. In many cases, it's difficult to Stefan> avoid using them, but in this case, calling a function after the Stefan> url-retrieve call works just as well, so there's no excuse. IIRC, in package.el I had to special-case some URL types, because headers are inconsistently used. E.g., I think the 'ftp' method won't leave headers in the buffer. It would be nice if this bit were handled by the url package rather than all the callers. Tom ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 15:19 ` Tom Tromey @ 2011-05-16 15:45 ` Stefan Monnier 2011-05-16 17:04 ` joakim 1 sibling, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2011-05-16 15:45 UTC (permalink / raw) To: Tom Tromey; +Cc: Ted Zlatanov, emacs-devel Stefan> While Emacs uses them a lot, dynamically-scoped variables used as Stefan> implicit extra parameters are bad. In many cases, it's difficult to Stefan> avoid using them, but in this case, calling a function after the Stefan> url-retrieve call works just as well, so there's no excuse. > IIRC, in package.el I had to special-case some URL types, because > headers are inconsistently used. E.g., I think the 'ftp' method won't > leave headers in the buffer. It would be nice if this bit were handled > by the url package rather than all the callers. Sounds like an inconsistency that needs fixing, indeed. You might want to make a bug-report for it. Stefan PS: Of course, that doesn't mean that the way to distinguish the "with header" and "without header" cases should be via a dynamically-scoped variable. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 15:19 ` Tom Tromey 2011-05-16 15:45 ` Stefan Monnier @ 2011-05-16 17:04 ` joakim 2011-05-16 17:17 ` Lennart Borgman ` (2 more replies) 1 sibling, 3 replies; 93+ messages in thread From: joakim @ 2011-05-16 17:04 UTC (permalink / raw) To: Tom Tromey; +Cc: Ted Zlatanov, Stefan Monnier, emacs-devel Tom Tromey <tromey@redhat.com> writes: >>>>>> "Stefan" == Stefan Monnier <monnier@iro.umontreal.ca> writes: > > Stefan> While Emacs uses them a lot, dynamically-scoped variables used as > Stefan> implicit extra parameters are bad. In many cases, it's difficult to > Stefan> avoid using them, but in this case, calling a function after the > Stefan> url-retrieve call works just as well, so there's no excuse. > > IIRC, in package.el I had to special-case some URL types, because > headers are inconsistently used. E.g., I think the 'ftp' method won't > leave headers in the buffer. It would be nice if this bit were handled > by the url package rather than all the callers. Changing (url-retrieve-synchronously URL) To (url-retrieve-synchronously URL &optional remove-headers) ought to sattisfy all participants in this thread? and it could be done somewhat like this: (defun url-retrieve-synchronously (url &optional remove-headers) (let ((buffer (url-retrieve-synchronously-old-implementation url)) (if remove-headers (url-remove-headers buffer )))) (defun url-remove-headers (buffer) (with-current-buffer buffer (widen) (goto-char (point-min)) (search-forward "\n\n") (delete-region (point-min) (point)) buffer) ) but we would also need to look out for the special cases Tom mentioned. Good enough? url-remove-headers is separate so it can be re-used in a url-retrieve callback for instance. > > Tom -- Joakim Verona ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 17:04 ` joakim @ 2011-05-16 17:17 ` Lennart Borgman 2011-05-16 17:30 ` Stefan Monnier 2011-05-16 18:39 ` Julien Danjou 2 siblings, 0 replies; 93+ messages in thread From: Lennart Borgman @ 2011-05-16 17:17 UTC (permalink / raw) To: joakim; +Cc: Tom Tromey, Ted Zlatanov, Stefan Monnier, emacs-devel On Mon, May 16, 2011 at 7:04 PM, <joakim@verona.se> wrote: > > Changing > (url-retrieve-synchronously URL) > To > (url-retrieve-synchronously URL &optional remove-headers) > > ought to sattisfy all participants in this thread? I did not follow, but you certainly want to check the headers many times. Perhaps optionally return a list with buffer + headers? ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 17:04 ` joakim 2011-05-16 17:17 ` Lennart Borgman @ 2011-05-16 17:30 ` Stefan Monnier 2011-05-16 18:39 ` Julien Danjou 2 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2011-05-16 17:30 UTC (permalink / raw) To: joakim; +Cc: Tom Tromey, Ted Zlatanov, emacs-devel > Changing > (url-retrieve-synchronously URL) > To > (url-retrieve-synchronously URL &optional remove-headers) > ought to sattisfy all participants in this thread? Let's first add the extra "remove-headers" function and fix Tom's issue. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-16 17:04 ` joakim 2011-05-16 17:17 ` Lennart Borgman 2011-05-16 17:30 ` Stefan Monnier @ 2011-05-16 18:39 ` Julien Danjou 2 siblings, 0 replies; 93+ messages in thread From: Julien Danjou @ 2011-05-16 18:39 UTC (permalink / raw) To: joakim; +Cc: Tom Tromey, Ted Zlatanov, Stefan Monnier, emacs-devel [-- Attachment #1: Type: text/plain, Size: 711 bytes --] On Mon, May 16 2011, joakim@verona.se wrote: > Changing > (url-retrieve-synchronously URL) > To > (url-retrieve-synchronously URL &optional remove-headers) > > ought to sattisfy all participants in this thread? Not sure it's a good idea. Having a function to remove/parse headers is more useful, and calling it like: (with-current-buffer (url-retrieve-synchronously URL) (url-remove-headers) (stuff)) seems enough to me. And, actually, most of the time you do not want especially to remove them but at least to go after them. This is a very common code to search-forward \n\n to move point after the headers. My 2¢, -- Julien Danjou ❱ http://julien.danjou.info [-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --] ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-14 10:32 more url-utils? joakim 2011-05-14 11:21 ` Lars Magne Ingebrigtsen 2011-05-14 13:21 ` Ted Zlatanov @ 2011-05-15 13:34 ` Chong Yidong 2011-05-17 22:26 ` Ted Zlatanov 2 siblings, 1 reply; 93+ messages in thread From: Chong Yidong @ 2011-05-15 13:34 UTC (permalink / raw) To: joakim; +Cc: emacs-devel joakim@verona.se writes: > Would the defun below be suitable to include in url-util? > You nearly always want to work with the data part of the document. > The code snippet below occurs a lot in different packages. > > A wrapper that downloads a file(like curl or wget) would be nice also. > > (defun org-feed-skip-http-headers (buffer) > "Remove HTTP headers from BUFFER, and return it. > Assumes headers are indeed present!" > (with-current-buffer buffer > (widen) > (goto-char (point-min)) > (search-forward "\n\n") > (delete-region (point-min) (point)) > buffer)) Good idea, though maybe the wrapper function should incorporate url-http-parse-response too (see the package-handle-response function in package.el). Please feel free to propose a patch. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-15 13:34 ` Chong Yidong @ 2011-05-17 22:26 ` Ted Zlatanov 2011-05-18 0:11 ` Stefan Monnier 0 siblings, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-17 22:26 UTC (permalink / raw) To: emacs-devel On Tue, 17 May 2011 00:04:50 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> Ah, OK. So my proposal does not fit because you want backwards >> compatibility. SM> I think that's right, although I'm not completely clear on what is SM> exactly your proposal. This is my proposal, after thinking about it for a bit. Current top-level API: Dynamic binding: `url-request-data', `url-request-method' and `url-request-extra-headers' according to the docstring; also according to a comment: url-standalone-mode, url-gateway-unplugged, w3-honor-stylesheets, url-confirmation-func, url-cookie-multiple-line, url-cookie-{{,secure-}storage,confirmation}. (defun url-retrieve (url callback &optional cbargs silent) ...) (defun url-retrieve-synchronously (url) ...) Both of these result in a buffer containing "[HEADERS] [BODY]" Proposed API (based on code review throughout Emacs and my feeling for what would be "natural" in ELisp): ;;; buffer-local variables: url-retrieved-ok url-headers-alist url-headers-as-string (defmacro with-url-contents-buffer (url url-options-alist callback-closure &rest body) ...) 1) Synchronous usage with errors: (with-url-contents-buffer "http://host" '((url-request-method "POST")) nil (message "this will run SYNCHRONOUSLY since the callback-closure is nil") (message "this could throw an error") (message "Header x is %s" (assq 'x url-headers-alist)) (message "Header y is %s" (assoc "y" url-headers-alist)) (message "The headers as a string are %s" url-headers-as-string) (when url-retrieved-ok (message "The retrieval went fine")) (message "data is %s" (buffer-string)) 2) Synchronous usage without errors: (with-url-contents-buffer "http://host" '((url-request-method "POST")) 'noerror (message "this will run SYNCHRONOUSLY since the callback-closure is nil") (message "this will not throw an error")) 3) Asynchronous usage with a callback (`url-headers-alist', `url-headers-as-string', and `url-retrieved-ok' are still available): (with-url-contents-buffer "http://host" '((url-request-method "POST")) callback-closure (message "this will run AFTER the retrieval and the callback-closure are done")) 4) Asynchronous usage with no callback (`url-headers-alist', `url-headers-as-string', and `url-retrieved-ok' are still available): (with-url-contents-buffer "http://host" '((url-request-method "POST")) t (message "this will run AFTER the retrieval is done, there is no callback")) Implicitly we don't have an asynchronous mode that throws errors. I also think we should have an incremental mode where each retrieved chunk is given to the callback in the buffer as it arrives. That would let us handle large downloads better. The API would not change, though, only the `url-options-alist' would have a `url-incremental' key and the callback would look at the buffer-local variable `url-incremental-byte-offset'. SM> If you can provide a patch that give us a clean new API together with SM> some backward compatibility layer, that would be great. After we've settled on the API, please. I think the above may be too different for many :) Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-17 22:26 ` Ted Zlatanov @ 2011-05-18 0:11 ` Stefan Monnier 2011-05-18 2:14 ` Ted Zlatanov 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2011-05-18 0:11 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel > 3) Asynchronous usage with a callback (`url-headers-alist', > `url-headers-as-string', and `url-retrieved-ok' are still available): > (with-url-contents-buffer "http://host" '((url-request-method "POST")) callback-closure > (message "this will run AFTER the retrieval and the callback-closure are done")) In which sense is this asynchronous? What's the difference between the code run in call-back-closure from the code in `body'? Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-18 0:11 ` Stefan Monnier @ 2011-05-18 2:14 ` Ted Zlatanov 2011-05-18 12:16 ` Stefan Monnier 0 siblings, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-18 2:14 UTC (permalink / raw) To: emacs-devel On Tue, 17 May 2011 21:11:23 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> 3) Asynchronous usage with a callback (`url-headers-alist', >> `url-headers-as-string', and `url-retrieved-ok' are still available): >> (with-url-contents-buffer "http://host" '((url-request-method "POST")) callback-closure >> (message "this will run AFTER the retrieval and the callback-closure are done")) SM> In which sense is this asynchronous? Same as the current url.el code. SM> What's the difference between the code run in call-back-closure from SM> the code in `body'? Since I'm proposing a macro, the callback-closure is funcalled while the body is inlined. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-18 2:14 ` Ted Zlatanov @ 2011-05-18 12:16 ` Stefan Monnier 2011-05-18 13:44 ` Ted Zlatanov 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2011-05-18 12:16 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel >>> 3) Asynchronous usage with a callback (`url-headers-alist', >>> `url-headers-as-string', and `url-retrieved-ok' are still available): >>> (with-url-contents-buffer "http://host" '((url-request-method "POST")) callback-closure >>> (message "this will run AFTER the retrieval and the callback-closure are done")) SM> In which sense is this asynchronous? > Same as the current url.el code. So you mean that, while the `body' is run after the retrieval is done, the code after with-url-contents-buffer will be run earlier? SM> What's the difference between the code run in call-back-closure from SM> the code in `body'? > Since I'm proposing a macro, the callback-closure is funcalled while the > body is inlined. I don't know what you mean by "funcalled vs inlined" (in my world, "inlined" means it's implemented slightly differently, but the behavior is identical). Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-18 12:16 ` Stefan Monnier @ 2011-05-18 13:44 ` Ted Zlatanov 2011-05-18 14:09 ` Stefan Monnier 0 siblings, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-18 13:44 UTC (permalink / raw) To: emacs-devel On Wed, 18 May 2011 09:16:07 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >>>> 3) Asynchronous usage with a callback (`url-headers-alist', >>>> `url-headers-as-string', and `url-retrieved-ok' are still available): >>>> (with-url-contents-buffer "http://host" '((url-request-method "POST")) callback-closure >>>> (message "this will run AFTER the retrieval and the callback-closure are done")) SM> In which sense is this asynchronous? >> Same as the current url.el code. SM> So you mean that, while the `body' is run after the retrieval is done, SM> the code after with-url-contents-buffer will be run earlier? Yes in the asynchronous case. This is just one case out of several the API supports and without a body this case behaves just like `url-retrieve'. If you don't think the asynchronous body is a good idea because it's hard to read, we can eliminate it by providing a separate function for the asynchronous case that only takes a callback-closure. To me it seems reasonable the way I've done it. SM> What's the difference between the code run in call-back-closure from SM> the code in `body'? The body is easier to write explicitly but the callback-closure offers more flexibility and backwards compatibility. They are more or less the same otherwise (see below for the pseudocode), it's just different types of syntactic sugar for different situations. I think the majority of uses will be in the synchronous mode, where `with-url-contents-buffer' is very convenient. >> Since I'm proposing a macro, the callback-closure is funcalled while the >> body is inlined. SM> I don't know what you mean by "funcalled vs inlined" (in my world, SM> "inlined" means it's implemented slightly differently, but the behavior SM> is identical). They are different because the resulting code is different, I don't know how to explain it any better. Maybe if I show the pseudocode? The body passed to the macro is inlined and the callback-closure is not, so the macro will look like this in the synchronous case: `(with-temp-buffer ... get url contents ... ,@(when callback-closure '(funcall callback-closure)) ,@body) I'll need to set up a lexical bind of the callback-closure to make this work, but I think it's reasonable otherwise. I can write the actual code if you agree. Or you can tell me how the API should look. The asynchronous case will be a bit more complicated, wrapping the body in a temporary closure and using that as a second callback. But as I said above we can disallow the body in the asynchronous mode if you think that's too complicated. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-18 13:44 ` Ted Zlatanov @ 2011-05-18 14:09 ` Stefan Monnier 2011-05-18 14:43 ` Ted Zlatanov 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2011-05-18 14:09 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel SM> What's the difference between the code run in call-back-closure from SM> the code in `body'? > The body is easier to write explicitly but the callback-closure offers > more flexibility and backwards compatibility. They are more or less the > same otherwise (see below for the pseudocode), it's just different types > of syntactic sugar for different situations. I think the majority of > uses will be in the synchronous mode, where `with-url-contents-buffer' > is very convenient. I think you're just afraid of lambda ;-0 Here's my proposal: (defun url-fetch (url &optional silent callback) "Fetch URL into current buffer. If CALLBACK is nil, do it synchronously and return a status flag." But I also like the idea of passing url-request-method and such as explicit arguments. And I'm not sure what it should return if CALLBACK is non-nil (both in the case where the request is performed asynchronously and when it's performed synchronously). Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-18 14:09 ` Stefan Monnier @ 2011-05-18 14:43 ` Ted Zlatanov 2011-05-18 22:05 ` Stefan Monnier 0 siblings, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-18 14:43 UTC (permalink / raw) To: emacs-devel On Wed, 18 May 2011 11:09:25 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: SM> What's the difference between the code run in call-back-closure from SM> the code in `body'? >> The body is easier to write explicitly but the callback-closure offers >> more flexibility and backwards compatibility. They are more or less the >> same otherwise (see below for the pseudocode), it's just different types >> of syntactic sugar for different situations. I think the majority of >> uses will be in the synchronous mode, where `with-url-contents-buffer' >> is very convenient. SM> I think you're just afraid of lambda ;-0 ...or are you afraid of macros? ;) SM> Here's my proposal: SM> (defun url-fetch (url &optional silent callback) SM> "Fetch URL into current buffer. SM> If CALLBACK is nil, do it synchronously and return a status flag." OK. The status flag should be nil on failure and t on success. Let's not tie the `url-fetch' status flag to the HTTP status. SM> But I also like the idea of passing url-request-method and such as SM> explicit arguments. (defun* url-fetch (url &rest spec &key silent callback request-data request-method request-extra-headers standalone-mode gateway-unplugged honor-stylesheets confirmation-func cookie-multiple-line cookie-storage cookie-confirmation cookie-secure-storage cookie-secure-confirmation &allow-other-keys) ...) This has less compile-time parameter validation but is much more flexible long-term. SM> And I'm not sure what it should return if CALLBACK is non-nil (both SM> in the case where the request is performed asynchronously and when SM> it's performed synchronously). By the docstring you gave, if CALLBACK is non-nil, it must be asynchronous. So CALLBACK can't be used synchronously. In the asynchronous mode we could return a lambda (see that? I used a lambda!) that can be evaluated to wait until CALLBACK completes and then returns whatever CALLBACK returned. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-18 14:43 ` Ted Zlatanov @ 2011-05-18 22:05 ` Stefan Monnier 2011-05-19 1:57 ` Ted Zlatanov 2011-05-19 13:46 ` ELisp futures and continuations/coroutines (was: more url-utils?) Ted Zlatanov 0 siblings, 2 replies; 93+ messages in thread From: Stefan Monnier @ 2011-05-18 22:05 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel SM> I think you're just afraid of lambda ;-0 > ...or are you afraid of macros? ;) That's partly true. But your `body' is nothing more than the body of the callback if passed as a lambda (and indeed within the macro you'll have to wrap `body' with a `lambda' to use it in the process-sentinel), so providing both `callback' and `body' arguments is not very useful. And of course `callback' has the advantage that it takes an argument (which will of course be `status') whereas `body' doesn't have such an easy and obvious access to the status. SM> But I also like the idea of passing url-request-method and such as SM> explicit arguments. > (defun* url-fetch > (url &rest spec > &key silent callback request-data request-method > request-extra-headers standalone-mode gateway-unplugged > honor-stylesheets confirmation-func cookie-multiple-line > cookie-storage cookie-confirmation cookie-secure-storage > cookie-secure-confirmation > &allow-other-keys) > ...) I'm not sure all those args make sense, but yes, that sounds about right. We should think hard about what those args should be, within the larger context of URL rather than only http. SM> And I'm not sure what it should return if CALLBACK is non-nil (both SM> in the case where the request is performed asynchronously and when SM> it's performed synchronously). > By the docstring you gave, if CALLBACK is non-nil, it must be > asynchronous. So CALLBACK can't be used synchronously. No, callback just makes it possible to do the request asynchronously, but it can still be performed synchronously and for some URLs we may not know how to perform them asynchronously (as the docstring of url-retrieve already explains). > In the asynchronous mode we could return a lambda (see that? I used a > lambda!) that can be evaluated to wait until CALLBACK completes and then ^^^^^^^^^ called > returns whatever CALLBACK returned. That's a good idea. Kind of like a future. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-18 22:05 ` Stefan Monnier @ 2011-05-19 1:57 ` Ted Zlatanov 2011-05-19 2:28 ` Stefan Monnier 2011-05-19 13:46 ` ELisp futures and continuations/coroutines (was: more url-utils?) Ted Zlatanov 1 sibling, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-19 1:57 UTC (permalink / raw) To: emacs-devel On Wed, 18 May 2011 19:05:57 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: SM> But your `body' is nothing more than the body of the callback if SM> passed as a lambda (and indeed within the macro you'll have to wrap SM> `body' with a `lambda' to use it in the process-sentinel), so SM> providing both `callback' and `body' arguments is not very useful. I thought it was more readable to cradle statements in a "with-xyz" macro (e.g. `with-temp-file', `with-parsed-tramp-file-name') than to craft a lambda for a callback. It's not a big deal, I can write the macro on top of `url-fetch' anyhow. >> (defun* url-fetch >> (url &rest spec >> &key silent callback request-data request-method >> request-extra-headers standalone-mode gateway-unplugged >> honor-stylesheets confirmation-func cookie-multiple-line >> cookie-storage cookie-confirmation cookie-secure-storage >> cookie-secure-confirmation >> &allow-other-keys) >> ...) SM> I'm not sure all those args make sense, but yes, that sounds SM> about right. We should think hard about what those args should be, SM> within the larger context of URL rather than only http. Yeah. So perhaps we simply write `url-http-fetch' that specifies the base `url-fetch' props and then adds its own list on top. SM> No, callback just makes it possible to do the request asynchronously, SM> but it can still be performed synchronously and for some URLs we may not SM> know how to perform them asynchronously (as the docstring of SM> url-retrieve already explains). OK. >> In the asynchronous mode we could return a lambda (see that? I used a >> lambda!) that can be evaluated to wait until CALLBACK completes and then SM> ^^^^^^^^^ SM> called >> returns whatever CALLBACK returned. SM> That's a good idea. Kind of like a future. All right, I'll provide that. Are you OK with the defun* approach and having each `url-{http,ftp,etc}-fetch' function build on the base `url-fetch'? Also I think the callback should get the status and then &rest plist. The plist will depend on the URL protocol but there will be common keys to determine the protocol, if there were headers, etc. That's a little bit less functional but the data will not be hidden in buffer-local variables like it is now (although those will still be available). There will be a lot more function parameters on the stack, though--I don't know if that's a problem. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-19 1:57 ` Ted Zlatanov @ 2011-05-19 2:28 ` Stefan Monnier 2011-05-19 10:28 ` Ted Zlatanov 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2011-05-19 2:28 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel > Yeah. So perhaps we simply write `url-http-fetch' that specifies the > base `url-fetch' props and then adds its own list on top. Hmm... maybe that's the right approach, indeed, but I wouldn't know (for lack of experience). > All right, I'll provide that. Are you OK with the defun* approach and Sure. > having each `url-{http,ftp,etc}-fetch' function build on the base > `url-fetch'? It doesn't sound too bad, tho maybe I'd have expected that url-fetch calls one of url-<transport>-fetch, rather than the other way around. > Also I think the callback should get the status and then &rest plist. > The plist will depend on the URL protocol but there will be common keys > to determine the protocol, if there were headers, etc. That's a little > bit less functional but the data will not be hidden in buffer-local > variables like it is now (although those will still be available). I think it's OK to use buffer-local vars to keep things like url-header-alist. [...] wait, it's OK to use buffer-local vars in a buffer created for the occasion (as in url-retrieve) but indeed if url-fetch stores the result in the current buffer as I suggested, then it's ugly to modify the buffer's local vars as a side-effect and it's better to pass it as an argument to the callback. > There will be a lot more function parameters on the stack, though--I > don't know if that's a problem. It's not a problem but I'd much prefer an "alist" than a "&rest plist". Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-19 2:28 ` Stefan Monnier @ 2011-05-19 10:28 ` Ted Zlatanov 2011-05-19 11:53 ` Stefan Monnier 0 siblings, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-19 10:28 UTC (permalink / raw) To: emacs-devel On Wed, 18 May 2011 23:28:41 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> All right, I'll provide that. Are you OK with the defun* approach and SM> Sure. OK, it's on my TODO list. >> Also I think the callback should get the status and then &rest plist. >> The plist will depend on the URL protocol but there will be common keys >> to determine the protocol, if there were headers, etc. That's a little >> bit less functional but the data will not be hidden in buffer-local >> variables like it is now (although those will still be available). SM> I think it's OK to use buffer-local vars to keep things like SM> url-header-alist. SM> [...] SM> wait, it's OK to use buffer-local vars in a buffer created for the SM> occasion (as in url-retrieve) but indeed if url-fetch stores the result SM> in the current buffer as I suggested, then it's ugly to modify the SM> buffer's local vars as a side-effect and it's better to pass it as an SM> argument to the callback. Right, `url-fetch' no longer implies `with-temp-buffer'. >> There will be a lot more function parameters on the stack, though--I >> don't know if that's a problem. SM> It's not a problem but I'd much prefer an "alist" than a "&rest SM> plist". OK. But if the status is nil we couldn't get any data so there are no URL properties. So we can have just one callback parameter "url-info" which is nil if the request failed and an alist if it worked. How would the callback find out what actually failed? Does it even need to? I think it's enough to know the request failed, the user can look in *Messages* to find out. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-19 10:28 ` Ted Zlatanov @ 2011-05-19 11:53 ` Stefan Monnier 2011-05-19 12:43 ` Ted Zlatanov 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2011-05-19 11:53 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel > OK. But if the status is nil we couldn't get any data so there are no > URL properties. So we can have just one callback parameter "url-info" > which is nil if the request failed and an alist if it worked. I think that a boolean status is not sufficient. E.g. in case of failure, we want to have some information about why (e.g. an error message). > How would the callback find out what actually failed? Does it even need > to? I think it's enough to know the request failed, the user can look > in *Messages* to find out. I don't think that's good enough. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-19 11:53 ` Stefan Monnier @ 2011-05-19 12:43 ` Ted Zlatanov 2011-05-19 13:28 ` Stefan Monnier 2011-05-19 14:11 ` joakim 0 siblings, 2 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-19 12:43 UTC (permalink / raw) To: emacs-devel On Thu, 19 May 2011 08:53:22 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> OK. But if the status is nil we couldn't get any data so there are no >> URL properties. So we can have just one callback parameter "url-info" >> which is nil if the request failed and an alist if it worked. SM> I think that a boolean status is not sufficient. E.g. in case of SM> failure, we want to have some information about why (e.g. an error SM> message). ..but we don't want to throw an error. Hrm. How about "url-info" is three possible types: 1) nil = failed, no information available (should happen only if there's no handler for the URL's protocol) 2) atom (string or symbol) = failed, information is the string or the symbol's properties 3) alist = success Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-19 12:43 ` Ted Zlatanov @ 2011-05-19 13:28 ` Stefan Monnier 2011-05-19 13:35 ` Ted Zlatanov 2011-05-30 17:31 ` Lars Magne Ingebrigtsen 2011-05-19 14:11 ` joakim 1 sibling, 2 replies; 93+ messages in thread From: Stefan Monnier @ 2011-05-19 13:28 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel >>> OK. But if the status is nil we couldn't get any data so there are no >>> URL properties. So we can have just one callback parameter "url-info" >>> which is nil if the request failed and an alist if it worked. SM> I think that a boolean status is not sufficient. E.g. in case of SM> failure, we want to have some information about why (e.g. an error SM> message). > ..but we don't want to throw an error. Hrm. How about "url-info" is > three possible types: > 1) nil = failed, no information available (should happen only if there's > no handler for the URL's protocol) > 2) atom (string or symbol) = failed, information is the string or the > symbol's properties How 'bout: the result of url-fetch (either returned in passed to the callback), is list of the form (STATUS . INFO): if STATUS is nil, it means the call was a success and INFO is an alist of auxiliary info such as headers and stuff, and if STATUS is non-nil, it should be an error symbol and INFO is some failure information such that one can do (signal (car result) (cdr result)). Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-19 13:28 ` Stefan Monnier @ 2011-05-19 13:35 ` Ted Zlatanov 2011-05-30 17:31 ` Lars Magne Ingebrigtsen 1 sibling, 0 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-19 13:35 UTC (permalink / raw) To: emacs-devel On Thu, 19 May 2011 10:28:05 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >>>> OK. But if the status is nil we couldn't get any data so there are no >>>> URL properties. So we can have just one callback parameter "url-info" >>>> which is nil if the request failed and an alist if it worked. SM> I think that a boolean status is not sufficient. E.g. in case of SM> failure, we want to have some information about why (e.g. an error SM> message). >> ..but we don't want to throw an error. Hrm. How about "url-info" is >> three possible types: >> 1) nil = failed, no information available (should happen only if there's >> no handler for the URL's protocol) >> 2) atom (string or symbol) = failed, information is the string or the >> symbol's properties SM> How 'bout: the result of url-fetch (either returned in passed to the SM> callback), is list of the form (STATUS . INFO): if STATUS is nil, it SM> means the call was a success and INFO is an alist of auxiliary info such SM> as headers and stuff, and if STATUS is non-nil, it should be an error SM> symbol and INFO is some failure information such that one can do SM> (signal (car result) (cdr result)). Sure, that's a nice solution. I'll use that. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-19 13:28 ` Stefan Monnier 2011-05-19 13:35 ` Ted Zlatanov @ 2011-05-30 17:31 ` Lars Magne Ingebrigtsen 2011-05-30 19:09 ` Stefan Monnier 1 sibling, 1 reply; 93+ messages in thread From: Lars Magne Ingebrigtsen @ 2011-05-30 17:31 UTC (permalink / raw) To: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: > How 'bout: the result of url-fetch (either returned in passed to the > callback), is list of the form (STATUS . INFO): if STATUS is nil, it > means the call was a success and INFO is an alist of auxiliary info such > as headers and stuff, and if STATUS is non-nil, it should be an error > symbol and INFO is some failure information such that one can do > (signal (car result) (cdr result)). Say you have a function that's supposed to do something with a web page, `parse-page'. The it would be very nice, I think, if the signature of that function could be the same no matter whether we're fetching the page synchronously or not. That is, it would be nice if it were possible to say either (apply #'parse-page (url-fetch "http://google.com")) to do it synchronously or say (url-fetch "http://google.com" 'parse-page) to do it asynchronously. This would imply that the signature used for callbacks should be something like (defun parse-page (buffer &optional status headers) ...) Does that make sense? -- (domestic pets only, the antidote for overdose, milk.) bloggy blog http://lars.ingebrigtsen.no/ ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-30 17:31 ` Lars Magne Ingebrigtsen @ 2011-05-30 19:09 ` Stefan Monnier 2011-05-30 19:38 ` Lars Magne Ingebrigtsen 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2011-05-30 19:09 UTC (permalink / raw) To: emacs-devel > That is, it would be nice if it were possible to say either > (apply #'parse-page (url-fetch "http://google.com")) > to do it synchronously or say > (url-fetch "http://google.com" 'parse-page) I was thinking of using > (funcall #'parse-page (url-fetch "http://google.com")) [...] > (url-fetch "http://google.com" 'parse-page) I.e. the callback takes a single argument. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-30 19:09 ` Stefan Monnier @ 2011-05-30 19:38 ` Lars Magne Ingebrigtsen 2011-05-30 22:17 ` Stefan Monnier 0 siblings, 1 reply; 93+ messages in thread From: Lars Magne Ingebrigtsen @ 2011-05-30 19:38 UTC (permalink / raw) To: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> (funcall #'parse-page (url-fetch "http://google.com")) > [...] >> (url-fetch "http://google.com" 'parse-page) > > I.e. the callback takes a single argument. Which would be a list of buffer/info/headers? Presently the callback is called with the current buffer set to the return buffer. If the async is to have the same signature as the sync, then that's not really practical. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog http://lars.ingebrigtsen.no/ ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-30 19:38 ` Lars Magne Ingebrigtsen @ 2011-05-30 22:17 ` Stefan Monnier 2011-05-30 23:11 ` Lars Magne Ingebrigtsen 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2011-05-30 22:17 UTC (permalink / raw) To: emacs-devel >>> (funcall #'parse-page (url-fetch "http://google.com")) >> [...] >>> (url-fetch "http://google.com" 'parse-page) >> I.e. the callback takes a single argument. > Which would be a list of buffer/info/headers? For example, yes. > Presently the callback is called with the current buffer set to the > return buffer. If the async is to have the same signature as the sync, > then that's not really practical. The sync case can set-buffer as well, so both choices are possible without breaking consistency. I don't have a strong preference either way. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-30 22:17 ` Stefan Monnier @ 2011-05-30 23:11 ` Lars Magne Ingebrigtsen 2011-05-31 1:26 ` Stefan Monnier 0 siblings, 1 reply; 93+ messages in thread From: Lars Magne Ingebrigtsen @ 2011-05-30 23:11 UTC (permalink / raw) To: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: > The sync case can set-buffer as well, so both choices are possible > without breaking consistency. I don't have a strong preference > either way. So calling (url-fetch "http://google.com") would change the current buffer? I think that sounds like very surprising behaviour... -- (domestic pets only, the antidote for overdose, milk.) bloggy blog http://lars.ingebrigtsen.no/ ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-30 23:11 ` Lars Magne Ingebrigtsen @ 2011-05-31 1:26 ` Stefan Monnier 2011-05-31 10:15 ` Lars Magne Ingebrigtsen 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2011-05-31 1:26 UTC (permalink / raw) To: emacs-devel >> The sync case can set-buffer as well, so both choices are possible >> without breaking consistency. I don't have a strong preference >> either way. > So calling (url-fetch "http://google.com") would change the current > buffer? I think that sounds like very surprising behaviour... Oh, wait, no, because I wanted url-fetch to insert the result in the current-buffer, rather than creating a brand new buffer. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-31 1:26 ` Stefan Monnier @ 2011-05-31 10:15 ` Lars Magne Ingebrigtsen 2011-05-31 12:45 ` Stefan Monnier 0 siblings, 1 reply; 93+ messages in thread From: Lars Magne Ingebrigtsen @ 2011-05-31 10:15 UTC (permalink / raw) To: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: > Oh, wait, no, because I wanted url-fetch to insert the result in the > current-buffer, rather than creating a brand new buffer. Yeah, that makes sense, perhaps. In the async case too? Hm. Are there any charset issues? I mean, if you're fetching an image, it's a binary thing, and if you want to allow already having stuff in the buffer, there might be issues... -- (domestic pets only, the antidote for overdose, milk.) bloggy blog http://lars.ingebrigtsen.no/ ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-31 10:15 ` Lars Magne Ingebrigtsen @ 2011-05-31 12:45 ` Stefan Monnier 2011-05-31 18:38 ` Lars Magne Ingebrigtsen 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2011-05-31 12:45 UTC (permalink / raw) To: emacs-devel >> Oh, wait, no, because I wanted url-fetch to insert the result in the >> current-buffer, rather than creating a brand new buffer. > Yeah, that makes sense, perhaps. In the async case too? Yes. > Hm. Are there any charset issues? I don't know what you're referring to. > I mean, if you're fetching an image, it's a binary thing, and if you > want to allow already having stuff in the buffer, there might be > issues... url-fetch could be defined to replace the current content of the buffer, if that's deemed necessary (i.e. mostly if it needs to use set-buffer-multibyte, which should ideally only ever be used on empty buffers). Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-31 12:45 ` Stefan Monnier @ 2011-05-31 18:38 ` Lars Magne Ingebrigtsen 0 siblings, 0 replies; 93+ messages in thread From: Lars Magne Ingebrigtsen @ 2011-05-31 18:38 UTC (permalink / raw) To: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: > url-fetch could be defined to replace the current content of the buffer, > if that's deemed necessary (i.e. mostly if it needs to use > set-buffer-multibyte, which should ideally only ever be used on empty > buffers). Right... so it wouldn't be like `insert-file-contents', where you'd get more stuff into a buffer already containing stuff. The normal synchronous calling pattern would be (with-temp-buffer (let ((info (url-fetch "http://google.com"))) ... do stuff)) while the async case would be (url-fetch "http://google.com" (lambda (info) ... do stuff)) Yeah, that looks nice to me. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog http://lars.ingebrigtsen.no/ ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-19 12:43 ` Ted Zlatanov 2011-05-19 13:28 ` Stefan Monnier @ 2011-05-19 14:11 ` joakim 2011-05-19 14:40 ` Stefan Monnier 1 sibling, 1 reply; 93+ messages in thread From: joakim @ 2011-05-19 14:11 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel Ted Zlatanov <tzz@lifelogs.com> writes: > On Thu, 19 May 2011 08:53:22 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: > >>> OK. But if the status is nil we couldn't get any data so there are no >>> URL properties. So we can have just one callback parameter "url-info" >>> which is nil if the request failed and an alist if it worked. > > SM> I think that a boolean status is not sufficient. E.g. in case of > SM> failure, we want to have some information about why (e.g. an error > SM> message). > > ..but we don't want to throw an error. Hrm. How about "url-info" is > three possible types: > > 1) nil = failed, no information available (should happen only if there's > no handler for the URL's protocol) > > 2) atom (string or symbol) = failed, information is the string or the > symbol's properties > > 3) alist = success This seems ok from my user-viewpoint. OTOH I wouldnt mind handling protocol errors with exceptions. Its what one does in many other languages anyway. BTW thanks everyone for driving this forward from my initial inadequate proposal! > > Ted > -- Joakim Verona ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: more url-utils? 2011-05-19 14:11 ` joakim @ 2011-05-19 14:40 ` Stefan Monnier 0 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2011-05-19 14:40 UTC (permalink / raw) To: joakim; +Cc: Ted Zlatanov, emacs-devel > This seems ok from my user-viewpoint. OTOH I wouldnt mind handling > protocol errors with exceptions. Its what one does in many other > languages anyway. For synchronous calls, signalling exceptions would be a better solution indeed. But that doesn't work nearly as well for the asynchronous case. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* ELisp futures and continuations/coroutines (was: more url-utils?) 2011-05-18 22:05 ` Stefan Monnier 2011-05-19 1:57 ` Ted Zlatanov @ 2011-05-19 13:46 ` Ted Zlatanov 2011-05-19 14:15 ` ELisp futures and continuations/coroutines Stefan Monnier ` (3 more replies) 1 sibling, 4 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-19 13:46 UTC (permalink / raw) To: emacs-devel On Wed, 18 May 2011 19:05:57 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: SM> That's a good idea. Kind of like a future. Speaking of futures, can we have a general facility for those? 1) a real "future" type 2) a way to construct it and check if the value is available 3) process sentinel tie-in I'm sure much of this facility is either possible or already available in ELisp, I just don't know the pieces and I think it would be very convenient to provide a "future" type. WDYT? Similarly it would be very nice to provide continuations and coroutines if those are not already possible. They don't need a top-level type though, a lexical closure is sufficient I think. Please tell me how I'm wrong :) Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-19 13:46 ` ELisp futures and continuations/coroutines (was: more url-utils?) Ted Zlatanov @ 2011-05-19 14:15 ` Stefan Monnier 2011-05-19 14:16 ` joakim ` (2 subsequent siblings) 3 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2011-05-19 14:15 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel SM> That's a good idea. Kind of like a future. > Speaking of futures, can we have a general facility for those? > 1) a real "future" type > 2) a way to construct it and check if the value is available > 3) process sentinel tie-in Patches welcome (preferably Elisp-only for a start). > I'm sure much of this facility is either possible or already available > in ELisp, I just don't know the pieces and I think it would be very > convenient to provide a "future" type. WDYT? I don't think it's already available, nor do I think similar things are commonly used currently. > Similarly it would be very nice to provide continuations and coroutines > if those are not already possible. They don't need a top-level type > though, a lexical closure is sufficient I think. Please tell me how I'm > wrong :) Given the way we implement the stack call/cc is difficult to implement. But the concurrency branch should make it easy to have coroutines. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-19 13:46 ` ELisp futures and continuations/coroutines (was: more url-utils?) Ted Zlatanov 2011-05-19 14:15 ` ELisp futures and continuations/coroutines Stefan Monnier @ 2011-05-19 14:16 ` joakim 2011-05-19 15:24 ` Ted Zlatanov 2011-05-19 15:09 ` Thien-Thi Nguyen 2011-05-19 17:03 ` ELisp futures and continuations/coroutines (was: more url-utils?) SAKURAI Masashi 3 siblings, 1 reply; 93+ messages in thread From: joakim @ 2011-05-19 14:16 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel Ted Zlatanov <tzz@lifelogs.com> writes: > On Wed, 18 May 2011 19:05:57 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: > > SM> That's a good idea. Kind of like a future. > > Speaking of futures, can we have a general facility for those? > > 1) a real "future" type > > 2) a way to construct it and check if the value is available > > 3) process sentinel tie-in > > I'm sure much of this facility is either possible or already available > in ELisp, I just don't know the pieces and I think it would be very > convenient to provide a "future" type. WDYT? > > Similarly it would be very nice to provide continuations and coroutines > if those are not already possible. They don't need a top-level type > though, a lexical closure is sufficient I think. Please tell me how I'm > wrong :) Continuations makes for very convenient web frameworks. Yum! > > Ted > -- Joakim Verona ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-19 14:16 ` joakim @ 2011-05-19 15:24 ` Ted Zlatanov 0 siblings, 0 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-19 15:24 UTC (permalink / raw) To: emacs-devel On Thu, 19 May 2011 16:16:30 +0200 joakim@verona.se wrote: j> Continuations makes for very convenient web frameworks. Yum! That's probably not useful for Emacs, but generally network interactions and iteration-oriented code are much easier when you can keep a continuation state. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-19 13:46 ` ELisp futures and continuations/coroutines (was: more url-utils?) Ted Zlatanov 2011-05-19 14:15 ` ELisp futures and continuations/coroutines Stefan Monnier 2011-05-19 14:16 ` joakim @ 2011-05-19 15:09 ` Thien-Thi Nguyen 2011-05-19 15:31 ` Ted Zlatanov 2011-05-19 17:03 ` ELisp futures and continuations/coroutines (was: more url-utils?) SAKURAI Masashi 3 siblings, 1 reply; 93+ messages in thread From: Thien-Thi Nguyen @ 2011-05-19 15:09 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel () Ted Zlatanov <tzz@lifelogs.com> () Thu, 19 May 2011 08:46:21 -0500 3) process sentinel tie-in What do you think of fsm.el for this? Hmm, i see it's not (yet?) a part of Emacs. -- a sig, not big, i fig, you dig? ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-19 15:09 ` Thien-Thi Nguyen @ 2011-05-19 15:31 ` Ted Zlatanov 2011-05-19 16:40 ` Thien-Thi Nguyen 0 siblings, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-19 15:31 UTC (permalink / raw) To: emacs-devel On Thu, 19 May 2011 17:09:25 +0200 Thien-Thi Nguyen <ttn@gnuvola.org> wrote: TN> () Ted Zlatanov <tzz@lifelogs.com> TN> () Thu, 19 May 2011 08:46:21 -0500 TN> 3) process sentinel tie-in TN> What do you think of fsm.el for this? TN> Hmm, i see it's not (yet?) a part of Emacs. You mean fsm-0.1ttn5.el from gnu.emacs.sources? (http://lists.gnu.org/archive/html/gnu-emacs-sources/2007-02/msg00006.html) Do you want to provide an example of how it would work to tie a hypothetical future type with process sentinels through fsm.el? It seems reasonable but I don't know enough to say. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-19 15:31 ` Ted Zlatanov @ 2011-05-19 16:40 ` Thien-Thi Nguyen 2011-05-19 23:48 ` Ted Zlatanov 0 siblings, 1 reply; 93+ messages in thread From: Thien-Thi Nguyen @ 2011-05-19 16:40 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel () Ted Zlatanov <tzz@lifelogs.com> () Thu, 19 May 2011 10:31:21 -0500 You mean fsm-0.1ttn5.el from gnu.emacs.sources? (http://lists.gnu.org/archive/html/gnu-emacs-sources/2007-02/msg00006.html) Yes, or the original (also to gnu-emacs-sources). Same idea. Do you want to provide an example of how it would work to tie a hypothetical future type with process sentinels through fsm.el? It seems reasonable but I don't know enough to say. No, because i don't know what such a future type would do. I just know that i have successfully (and more pleasantly than initially imagined) used fsm to implement a multicast proxy server (1 in, N out), which had as its core requirement, the ability to chunk computation into disparate pieces to be evaluated later. From this congruent experience, i would guess that a "future type" would be some subset of the fsm internals. Analogous to the "keymap type", which is really just a list with symbol ‘keymap’ in its CAR, i am guessing one could poke around fsm internals and derive a "future type", without having to go to C. Which is to say, i also don't know enough to say, but i see a similarity. -- a sig, not big, i fig, you dig? ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-19 16:40 ` Thien-Thi Nguyen @ 2011-05-19 23:48 ` Ted Zlatanov 2011-05-20 1:23 ` Thien-Thi Nguyen 0 siblings, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-19 23:48 UTC (permalink / raw) To: emacs-devel On Thu, 19 May 2011 18:40:47 +0200 Thien-Thi Nguyen <ttn@gnuvola.org> wrote: TN> i don't know what such a future type would do. ... TN> i would guess that a "future type" would be some subset of the fsm TN> internals. Why tie futures to fsm.el or deferred.el specifically? That seems like an implementation detail. I'd rather establish a futures API: - create a future - is it done? - get result - inspect thrown error, if any which is simple, obviously, but it's essential so all the implementations that use it speak the same language. TN> Analogous to the "keymap type", which is really just a list with symbol TN> ‘keymap’ in its CAR, i am guessing one could poke around fsm internals TN> and derive a "future type", without having to go to C. TN> Which is to say, i also don't know enough to say, but i see a similarity. Yes, it could be that way, or it could be a defstruct as in the deferred.el Masashi-san posted. Ideally no C code would be needed. I like the defstruct because it's simple yet has structure and accessor functions. I would copy the deferred defstruct without the `next' or `cancel' fields and without any callback/errorback defaults. Here's a first cut, pretty trivial code: #+begin_src lisp (defstruct future callback errorback status value) (defun future-done-p (future) (future-status future)) (defun future-errored-p (future) (eq (future-status future) 'error)) (defun future-finish (future &optional status) (unless (future-done-p future) (setf (future-status future) (or status t)) (when (future-callback future) (funcall (future-callback future) future)))) (defun future-errored (future error) (unless (future-done-p future) (setf (future-status future) 'error) (when (future-errorback future) (funcall (future-errorback future) future error)))) (defun future-call (future) (unless (future-done-p future) (let ((ff (future-value future))) (when (functionp ff) ;; TODO: needs error handling (setf (future-value future) (funcall ff)))) (future-finish future))) #+end_src `future-errored-p' breaks if the return value is 'error, though the correct callback will be invoked even then. I like the name "future" because it's fairly standard nowadays, it's a noun unlike "deferred," there are no global functions or variables with that string in Emacs except some org-mode variables, and it's very clear. If the above looks OK I can finish the implementation (error handling in `future-call' and around the callback/errorback invocations). Then any library can use ":include future" to add its own details on top of the `future' defstruct. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-19 23:48 ` Ted Zlatanov @ 2011-05-20 1:23 ` Thien-Thi Nguyen 2011-05-20 4:18 ` Mohsen BANAN 2011-05-20 15:29 ` Ted Zlatanov 0 siblings, 2 replies; 93+ messages in thread From: Thien-Thi Nguyen @ 2011-05-20 1:23 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel () Ted Zlatanov <tzz@lifelogs.com> () Thu, 19 May 2011 18:48:49 -0500 Why tie futures to fsm.el or deferred.el specifically? That seems like an implementation detail. Well, one important detail, whether you consider it implementation or design, is who kicks the evaluation (and when). In the case of fsm.el, this is done by either a timer or from process input. A "future type" w/o this detail well-defined is no better than a simple closure (IMHO) because it has no concept of time / timing. Since invocation must be well-defined, so must the reception and stashing of the returned value(s) be done in a coordinated way. I think the "hello world" (demonstrating minimal sufficiency) of such a system is countdown timer. I'd rather establish a futures API: - create a future - is it done? - get result - inspect thrown error, if any which is simple, obviously, but it's essential so all the implementations that use it speak the same language. The answer to "is it done" is "never", if it never is kicked, tickled, invoked, prodded, probed, or otherwise moved to action. I like the defstruct because it's simple Yes, it's much cleaner than fsm's plist munging, but (as i tried to express above), that is just the shape of the sail and not the motion of the boat. (defstruct future callback errorback status value) [...] Keep going! If the above looks OK I can finish the implementation (error handling in `future-call' and around the callback/errorback invocations). Then any library can use ":include future" to add its own details on top of the `future' defstruct. Minimalism is nice, but i suppose i like a more full-featured "future type", one that can self-terminate, for example. Conniving computers, grumble... (i'll have to dig up and post some old fsm toys -- get a dozen of them going at once and you'll see what i mean :-D). -- a sig, not big, i fig, you dig? ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-20 1:23 ` Thien-Thi Nguyen @ 2011-05-20 4:18 ` Mohsen BANAN 2011-05-20 15:30 ` Ted Zlatanov 2011-05-20 15:29 ` Ted Zlatanov 1 sibling, 1 reply; 93+ messages in thread From: Mohsen BANAN @ 2011-05-20 4:18 UTC (permalink / raw) To: Thien-Thi Nguyen; +Cc: Ted Zlatanov, emacs-devel >>>>> On Fri, 20 May 2011 03:23:57 +0200, Thien-Thi Nguyen <ttn@gnuvola.org> said: Thien-Thi> A "future type" w/o this detail well-defined is no better than Thien-Thi> a simple closure (IMHO) because it has no concept of time / timing. If the point is that: This is not a case of either or, but both. then, I agree. In which case if there is meaningful room for layering, then great! But, I don't suspect much. In any case, here is a pointer to a C fsm interface, documentation and examples that I built and used (in RFC-2188, RFC-2524, ...) 15 years ago. http://www.neda.com/PLPC/110301#x1-1520006.19 I am in no way suggesting its inclusion. But the documentation is relatively good and may be worth reusing. ...Mohsen ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-20 4:18 ` Mohsen BANAN @ 2011-05-20 15:30 ` Ted Zlatanov 0 siblings, 0 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-20 15:30 UTC (permalink / raw) To: emacs-devel On Thu, 19 May 2011 21:18:50 -0700 Mohsen BANAN <list-general@mohsen.1.banan.byname.net> wrote: MB> In any case, here is a pointer to a C fsm MB> interface, documentation and examples that I built MB> and used (in RFC-2188, RFC-2524, ...) 15 years ago. MB> http://www.neda.com/PLPC/110301#x1-1520006.19 That brings back memories of using ObjectTime (a FSM programming IDE) back in college :) Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-20 1:23 ` Thien-Thi Nguyen 2011-05-20 4:18 ` Mohsen BANAN @ 2011-05-20 15:29 ` Ted Zlatanov 2011-05-22 13:17 ` Thien-Thi Nguyen 1 sibling, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-20 15:29 UTC (permalink / raw) To: emacs-devel On Fri, 20 May 2011 03:23:57 +0200 Thien-Thi Nguyen <ttn@gnuvola.org> wrote: TN> () Ted Zlatanov <tzz@lifelogs.com> TN> () Thu, 19 May 2011 18:48:49 -0500 TN> Why tie futures to fsm.el or deferred.el specifically? That seems like TN> an implementation detail. TN> Well, one important detail, whether you consider it implementation TN> or design, is who kicks the evaluation (and when). In the case of TN> fsm.el, this is done by either a timer or from process input. Yes, but deferred.el does it with a timer-triggered queue drain, storing the next deferred item in the current one, and the concurrency branch might do it with a separate thread. These implementation details obscure the purpose of the "future" type: to hold a potential value. TN> A "future type" w/o this detail well-defined is no better than TN> a simple closure (IMHO) because it has no concept of time / timing. ... TN> Minimalism is nice, but i suppose i like a more full-featured "future type", TN> one that can self-terminate, for example. Conniving computers, grumble... TN> (i'll have to dig up and post some old fsm toys -- get a dozen of them going TN> at once and you'll see what i mean :-D). Why should a future type encapsulate any time knowledge? The whole point is that you don't know when and if it will be available. You could derive a expected-future which will have some knowledge of when it might have the data. A self-managed-future could run its own functions. And so on. But I really want a clean, simple API that can be used by any library. Let's get this done, simple though it is, and then see how it will integrate with fsm.el and deferred.el. I really think it will benefit everyone to start simple. TN> Yes, [defstruct is] much cleaner than fsm's plist munging, but (as i TN> tried to express above), that is just the shape of the sail and not TN> the motion of the boat. Heh heh. I guess we're close to land then. TN> Keep going! The below adds a way to cancel a future. I think error handling is all that's left unsaid. Ted #+begin_src lisp (defstruct future callback errorback status value) (defun future-done-p (future) (future-status future)) (defun future-errored-p (future) (eq (future-status future) 'error)) (defun future-cancelled-p (future) (eq (future-status future) 'cancel)) (defun future-finish (future &optional status) (unless (future-done-p future) (setf (future-status future) (or status t)) (when (future-callback future) (funcall (future-callback future) future)))) (defun future-errored (future error) (unless (future-done-p future) (setf (future-status future) 'error) (when (future-errorback future) (funcall (future-errorback future) future error)))) (defun future-call (future) (unless (future-done-p future) (let ((ff (future-value future))) (when (functionp ff) ;; TODO: needs error handling (setf (future-value future) (funcall ff)))) (future-finish future))) (defun future-cancel (future) (unless (future-done-p future) (future-finish future 'cancel))) #+end_src ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-20 15:29 ` Ted Zlatanov @ 2011-05-22 13:17 ` Thien-Thi Nguyen 2011-05-23 14:24 ` Ted Zlatanov 0 siblings, 1 reply; 93+ messages in thread From: Thien-Thi Nguyen @ 2011-05-22 13:17 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel () Ted Zlatanov <tzz@lifelogs.com> () Fri, 20 May 2011 10:29:39 -0500 [knowledge of time is design, not implementation, thus out of scope of the proposed "future type"] Ok, i can respect that. Let's get this done, simple though it is, and then see how it will integrate with fsm.el and deferred.el. I really think it will benefit everyone to start simple. #+begin_src lisp (defstruct future callback errorback status value) (defun future-done-p (future) (future-status future)) (defun future-errored-p (future) (eq (future-status future) 'error)) (defun future-cancelled-p (future) (eq (future-status future) 'cancel)) (defun future-finish (future &optional status) (unless (future-done-p future) (setf (future-status future) (or status t)) (when (future-callback future) (funcall (future-callback future) future)))) (defun future-errored (future error) (unless (future-done-p future) (setf (future-status future) 'error) (when (future-errorback future) (funcall (future-errorback future) future error)))) (defun future-call (future) (unless (future-done-p future) (let ((ff (future-value future))) (when (functionp ff) ;; TODO: needs error handling (setf (future-value future) (funcall ff)))) (future-finish future))) (defun future-cancel (future) (unless (future-done-p future) (future-finish future 'cancel))) #+end_src The next step (speaking from an armchair designer's pov) would be to rebase fsm.el and deferred.el onto this data structure. before: fsm: deferred: API API internals internals after: fsm: deferred: API API fsm glue deferred glue struct ‘future’ struct ‘future’ I guess there will be similarities between the fsm and deferred glue that we'd be wise to "move" into ‘struct future’, but that remains to be seen. -- a sig, not big, i fig, you dig? ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-22 13:17 ` Thien-Thi Nguyen @ 2011-05-23 14:24 ` Ted Zlatanov 2011-05-23 14:59 ` Stefan Monnier 0 siblings, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-23 14:24 UTC (permalink / raw) To: emacs-devel [-- Attachment #1: Type: text/plain, Size: 975 bytes --] On Sun, 22 May 2011 15:17:32 +0200 Thien-Thi Nguyen <ttn@gnuvola.org> wrote: TN> () Ted Zlatanov <tzz@lifelogs.com> TN> () Fri, 20 May 2011 10:29:39 -0500 TZZ> Let's get this done, simple though it is, and then see how it will TZZ> integrate with fsm.el and deferred.el. I really think it will benefit TZZ> everyone to start simple. ... TN> The next step (speaking from an armchair designer's pov) would be TN> to rebase fsm.el and deferred.el onto this data structure. Stefan, Chong, anyone else, please let me know if you have objections to the attached future.el package. I will add error handling and add it to Emacs tonight if there are no objections. It's pretty simple code. TN> I guess there will be similarities between the fsm and deferred glue that TN> we'd be wise to "move" into ‘struct future’, but that remains to be seen. I'll gladly modify it if we find such similarities once we start reworking fsm.el and deferred.el to use it. Ted [-- Attachment #2: future.el --] [-- Type: application/emacs-lisp, Size: 2084 bytes --] ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-23 14:24 ` Ted Zlatanov @ 2011-05-23 14:59 ` Stefan Monnier 2011-05-23 15:10 ` Ted Zlatanov 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2011-05-23 14:59 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel > Stefan, Chong, anyone else, please let me know if you have objections to > the attached future.el package. I will add error handling and add it to > Emacs tonight if there are no objections. It's pretty simple code. IIUC this will only be used by URL, at least at first. Is there any other package which is likely to use it in the foreseeable "future"? If not, then I'd recommend to name it "url-future" for now. Stefan PS: I'd expect future-finish and future-errored to signal an error is the future is already done-p. And future-call should return the future-value. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-23 14:59 ` Stefan Monnier @ 2011-05-23 15:10 ` Ted Zlatanov 2011-05-23 15:42 ` SAKURAI Masashi 2011-05-23 15:45 ` Stefan Monnier 0 siblings, 2 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-23 15:10 UTC (permalink / raw) To: emacs-devel [-- Attachment #1: Type: text/plain, Size: 1129 bytes --] On Mon, 23 May 2011 11:59:02 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> Stefan, Chong, anyone else, please let me know if you have objections to >> the attached future.el package. I will add error handling and add it to >> Emacs tonight if there are no objections. It's pretty simple code. SM> IIUC this will only be used by URL, at least at first. Is there any SM> other package which is likely to use it in the foreseeable "future"? SM> If not, then I'd recommend to name it "url-future" for now. The idea from the beginning was that this is a true data type, not an auxiliary library. At least deferred.el and fsm.el will use it, and I am in favor of adding deferred.el to Emacs as I mentioned. I would rather not isolate its scope to just URL interactions because rewriting url-future-* to future-* later will be annoying and because it makes the package look like it has narrow utility. SM> PS: I'd expect future-finish and future-errored to signal an error is SM> the future is already done-p. And future-call should return the SM> future-value. Thanks, I made those changes, see attached. Ted [-- Attachment #2: future.el --] [-- Type: application/emacs-lisp, Size: 2294 bytes --] ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-23 15:10 ` Ted Zlatanov @ 2011-05-23 15:42 ` SAKURAI Masashi 2011-05-25 2:07 ` Ted Zlatanov 2011-05-23 15:45 ` Stefan Monnier 1 sibling, 1 reply; 93+ messages in thread From: SAKURAI Masashi @ 2011-05-23 15:42 UTC (permalink / raw) To: emacs-devel At Mon, 23 May 2011 10:10:44 -0500, Ted Zlatanov wrote: > : > The idea from the beginning was that this is a true data type, not an > auxiliary library. At least deferred.el and fsm.el will use it, and I > am in favor of adding deferred.el to Emacs as I mentioned. What can I do to add deferred.el to Emacs ? -- SAKURAI, Masashi (family, given) ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-23 15:42 ` SAKURAI Masashi @ 2011-05-25 2:07 ` Ted Zlatanov 2011-05-26 0:23 ` SAKURAI Masashi 2011-06-03 13:59 ` SAKURAI Masashi 0 siblings, 2 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-25 2:07 UTC (permalink / raw) To: emacs-devel On Tue, 24 May 2011 00:42:58 +0900 SAKURAI Masashi <m.sakurai@kiwanami.net> wrote: SM> At Mon, 23 May 2011 10:10:44 -0500, SM> Ted Zlatanov wrote: >> : >> The idea from the beginning was that this is a true data type, not an >> auxiliary library. At least deferred.el and fsm.el will use it, and I >> am in favor of adding deferred.el to Emacs as I mentioned. SM> What can I do to add deferred.el to Emacs ? You need to sign the assignment papers and then I can add it to the GNU ELPA, which is the Emacs 24 package repository. It may get moved to the Emacs core later, depending on how widely it's used, but in the GNU ELPA it will be very easy to find and install. Also please see the discussion in this thread about url-future.el. If you can consider augmenting that defstruct instead of using the one in deferred.el, it would be nice so we're all speaking the same data language. I asked the same of Thien-Thi Nguyen for fsm.el. But it's not a requirement for inclusion in the GNU ELPA and you don't have to do it. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-25 2:07 ` Ted Zlatanov @ 2011-05-26 0:23 ` SAKURAI Masashi 2011-06-03 13:59 ` SAKURAI Masashi 1 sibling, 0 replies; 93+ messages in thread From: SAKURAI Masashi @ 2011-05-26 0:23 UTC (permalink / raw) To: tzz; +Cc: emacs-devel At Tue, 24 May 2011 21:07:50 -0500, Ted Zlatanov wrote: > : > SM> What can I do to add deferred.el to Emacs ? > > You need to sign the assignment papers and then I can add it to the GNU > ELPA, which is the Emacs 24 package repository. It may get moved to the > Emacs core later, depending on how widely it's used, but in the GNU ELPA > it will be very easy to find and install. Thank you for your advice. I sent my signing request form to gnu. I have to learn the GNU ELPA. > Also please see the discussion in this thread about url-future.el. If > you can consider augmenting that defstruct instead of using the one in > deferred.el, it would be nice so we're all speaking the same data > language. I asked the same of Thien-Thi Nguyen for fsm.el. But it's > not a requirement for inclusion in the GNU ELPA and you don't have to do > it. I am reading the thread to catch up the discussion. I will comment as soon as possible. -- SAKURAI, Masashi (family, given) ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-25 2:07 ` Ted Zlatanov 2011-05-26 0:23 ` SAKURAI Masashi @ 2011-06-03 13:59 ` SAKURAI Masashi 2011-06-03 16:06 ` Ted Zlatanov 1 sibling, 1 reply; 93+ messages in thread From: SAKURAI Masashi @ 2011-06-03 13:59 UTC (permalink / raw) To: tzz; +Cc: emacs-devel At Tue, 24 May 2011 21:07:50 -0500, Ted Zlatanov wrote: > : > Also please see the discussion in this thread about url-future.el. If > you can consider augmenting that defstruct instead of using the one in > deferred.el, it would be nice so we're all speaking the same data > language. I asked the same of Thien-Thi Nguyen for fsm.el. But it's > not a requirement for inclusion in the GNU ELPA and you don't have to do > it. I have read all discussion messages in this thread (about more url-utils and future in elisp) carefully at last. Those discussions are so interesting. I wrote my comment as follows. Sorry for long comment. About the "future" type for the just url-fetch function, I think it is good enough to transfer values asynchronously to the waiting function. However, I think it is somewhat primitive to construct general asynchronous programs. I have met so many difficulties during developing some Emacs applications[1] which has rich UIs and communication with external resources, such as handling many callbacks and waiting for them to finish. For example, getting images by wget -> making thumbnails -> displaying the images in the buffer, during then, the application notifies the user of progress of tasks and may display results or error messages. OTOH, in JavaScript, there are async supports in many major libs: jQuery.Deferred, Mochikit.Async, dojo.Deferred and so on. We can easily write async codes right now. Now, even .NET4[2] provides an async lib like JSDeferred. So, I'm sure elisp should have async support too. While I'm not a researcher for the concurrent programing, investigating such other async libraries, I found that asynchronous programing needs at least following two functions: 1) sequential connecting 2) waiting for async tasks done (all of them or the earliest one). One can define many other aspects of async programing. Ex. composition of tasks, error handling, canceling, propagating values, adding tasks after executed, restarting tasks, notifying progress and so on[3]. Recently, I found an utility program url-queue.el (Fetching web pages in parallel) was added to lisp/url in trunk. In the single-thread model like the Emacs, the task queue requires the callback interface. So, I think some library which supports concurrent programing model will be needed in near future, like deferred.el and concurrent.el. Furthermore, url-queue.el seems to implement the semaphore which is one of concurrent patterns. I made the semaphore in concurrent.el because I needed. I have also seen the similar code in emacs-w3m[4]. The code of w3m-proc.el manages number of sub-processes and abstraction of async and sync calling. So, I think those concurrent patterns have been needed already. Though concurrent.el has some patterns those were implemented for my applications, of course, it doesn't cover all patterns. According to other languages and some books, STM, Agent, Actor, Reentrant Lock and Read-Write Lock are argued as concurrent programing. Last, if my experience of development of deferred.el and concurrent.el would help the Emacs's advance, I would be happy. I don't mind if the libraries will be added to GNU ELPA or Emacs, even the maintainers write a subset code from scratch. Foot notes: [1] My deferred.el applications * A network multiplayer game which I mentioned the previous post. https://github.com/kiwanami/emacs-3d-demo (movie) http://www.youtube.com/watch?v=YS5CUj9oUhs * In-line image manager with cacoo.com, the on-line diagramming tool https://github.com/kiwanami/emacs-cacoo (movie) http://www.youtube.com/watch?v=pwZvT5HFQjY * PDF file manager https://github.com/kiwanami/emacs-anything-books (movie) http://www.youtube.com/watch?v=jfEHmgCIc08 * Inertial scrolling (see the movie of cacoo.el) https://github.com/kiwanami/emacs-inertial-scroll [2] .NET * Async Tasks - Simplify Asynchronous Programming with Tasks http://msdn.microsoft.com/en-us/magazine/ff959203.aspx Moreover, Task and Rx enables to collect async resources by LINQ * Reactive Extensions http://msdn.microsoft.com/en-us/data/gg577609 [3] Aspects of async libs Sorry for only Japanese article I found. * (in Japanese) http://digitechlog.com/2010/03/12/7-asynchronous-processing-open-source-actionscript-library.html * (machine translation) http://translate.google.co.jp/translate?hl=ja&sl=ja&tl=en&u=http://digitechlog.com/2010/03/12/7-asynchronous-processing-open-source-actionscript-library.html Following article may be helpful for designing async lib. * Virtual Panel: How to Survive Asynchronous Programming in JavaScript (InfoQ) http://www.infoq.com/articles/surviving-asynchronous-programming-in-javascript [4] Emacs-w3m * web site: http://emacs-w3m.namazu.org/index-en.html * w3m-proc.el: http://cvs.namazu.org/emacs-w3m/w3m-proc.el?view=markup -- SAKURAI, Masashi (family, given) ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-06-03 13:59 ` SAKURAI Masashi @ 2011-06-03 16:06 ` Ted Zlatanov 2011-06-04 6:21 ` SAKURAI Masashi 2011-06-29 5:31 ` SAKURAI Masashi 0 siblings, 2 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-06-03 16:06 UTC (permalink / raw) To: emacs-devel On Fri, 03 Jun 2011 22:59:48 +0900 SAKURAI Masashi <m.sakurai@kiwanami.net> wrote: SM> At Tue, 24 May 2011 21:07:50 -0500, SM> Ted Zlatanov wrote: >> : >> Also please see the discussion in this thread about url-future.el. If >> you can consider augmenting that defstruct instead of using the one in >> deferred.el, it would be nice so we're all speaking the same data >> language. I asked the same of Thien-Thi Nguyen for fsm.el. But it's >> not a requirement for inclusion in the GNU ELPA and you don't have to do >> it. SM> About the "future" type for the just url-fetch function, I think it is SM> good enough to transfer values asynchronously to the waiting function. SM> However, I think it is somewhat primitive to construct general SM> asynchronous programs. The future type is intentionally a simple pure data type. It can be extended with `defstruct'. Is the data type missing something you need? Can you convert concurrent.el to derive its data type from the url-future struct and use the url-future-* functions, or is there something blocking that conversion? When I looked at concurrent.el, the data type it uses was very similar to the url-future defstruct. SM> While I'm not a researcher for the concurrent programing, SM> investigating such other async libraries, I found that asynchronous SM> programing needs at least following two functions: SM> 1) sequential connecting SM> 2) waiting for async tasks done (all of them or the earliest one). SM> One can define many other aspects of async programing. SM> Ex. composition of tasks, error handling, canceling, propagating SM> values, adding tasks after executed, restarting tasks, notifying SM> progress and so on[3]. Sure, but all of these are functional requirements. url-future.el only addressed the "futures" protocol, so we can speak a common data language. It doesn't provide any actual async support. That's the job for concurrent.el and deferred.el among others. SM> Though concurrent.el has some patterns those were implemented for my SM> applications, of course, it doesn't cover all patterns. According to SM> other languages and some books, STM, Agent, Actor, Reentrant Lock and SM> Read-Write Lock are argued as concurrent programing. I'm not sure how much of that is needed in Emacs. Perhaps these needs will become more apparent when the concurrency branch is merged, though I have no idea when that will hapen. SM> Last, if my experience of development of deferred.el and concurrent.el SM> would help the Emacs's advance, I would be happy. I don't mind if SM> the libraries will be added to GNU ELPA or Emacs, even the maintainers SM> write a subset code from scratch. You need to sign the assignment papers. One of the Emacs maintainers can help you with that. I think assign@gnu.org is the general contact point for any copyright assignment questions. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-06-03 16:06 ` Ted Zlatanov @ 2011-06-04 6:21 ` SAKURAI Masashi 2011-06-29 5:31 ` SAKURAI Masashi 1 sibling, 0 replies; 93+ messages in thread From: SAKURAI Masashi @ 2011-06-04 6:21 UTC (permalink / raw) To: emacs-devel At Fri, 03 Jun 2011 11:06:22 -0500, Ted Zlatanov wrote: > : > Sure, but all of these are functional requirements. url-future.el only > addressed the "futures" protocol, so we can speak a common data > language. It doesn't provide any actual async support. That's the job > for concurrent.el and deferred.el among others. I have understood "speaking a common data language" you mentioned. OK. I see. I would try to modify deferred.el to fit the data type, after I check the code of the url-fetch. > SM> Though concurrent.el has some patterns those were implemented for my > SM> applications, of course, it doesn't cover all patterns. According to > SM> other languages and some books, STM, Agent, Actor, Reentrant Lock and > SM> Read-Write Lock are argued as concurrent programing. > > I'm not sure how much of that is needed in Emacs. Perhaps these needs > will become more apparent when the concurrency branch is merged, though > I have no idea when that will hapen. I see. Recently I'm interesting in the Emacs as an application runtime environment. So, I'm also interesting in the thread 'Emacs as a desktop environment'. > SM> Last, if my experience of development of deferred.el and concurrent.el > SM> would help the Emacs's advance, I would be happy. I don't mind if > SM> the libraries will be added to GNU ELPA or Emacs, even the maintainers > SM> write a subset code from scratch. > > You need to sign the assignment papers. One of the Emacs maintainers > can help you with that. I think assign@gnu.org is the general contact > point for any copyright assignment questions. I sent my request to assign@gnu.org in last month, and I'm waiting for assignment papers from gnu.org. -- SAKURAI, Masashi (family, given) ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-06-03 16:06 ` Ted Zlatanov 2011-06-04 6:21 ` SAKURAI Masashi @ 2011-06-29 5:31 ` SAKURAI Masashi 2011-06-29 12:01 ` Ted Zlatanov 2011-06-29 16:09 ` Chong Yidong 1 sibling, 2 replies; 93+ messages in thread From: SAKURAI Masashi @ 2011-06-29 5:31 UTC (permalink / raw) To: emacs-devel > SM> Last, if my experience of development of deferred.el and concurrent.el > SM> would help the Emacs's advance, I would be happy. I don't mind if > SM> the libraries will be added to GNU ELPA or Emacs, even the maintainers > SM> write a subset code from scratch. > > You need to sign the assignment papers. One of the Emacs maintainers > can help you with that. I think assign@gnu.org is the general contact > point for any copyright assignment questions. I have signed and received the assignment paper copy. I would learn the GNU ELPA. I'm going to check the emacs-devel threads about the ELPA. Which documents should I read? ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-06-29 5:31 ` SAKURAI Masashi @ 2011-06-29 12:01 ` Ted Zlatanov 2011-06-29 17:33 ` SAKURAI Masashi 2011-06-29 16:09 ` Chong Yidong 1 sibling, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-06-29 12:01 UTC (permalink / raw) To: emacs-devel On Wed, 29 Jun 2011 14:31:32 +0900 SAKURAI Masashi <m.sakurai@kiwanami.net> wrote: SM> Last, if my experience of development of deferred.el and concurrent.el SM> would help the Emacs's advance, I would be happy. I don't mind if SM> the libraries will be added to GNU ELPA or Emacs, even the maintainers SM> write a subset code from scratch. >> >> You need to sign the assignment papers. One of the Emacs maintainers >> can help you with that. I think assign@gnu.org is the general contact >> point for any copyright assignment questions. SM> I have signed and received the assignment paper copy. I would learn SM> the GNU ELPA. I'm going to check the emacs-devel threads about the SM> ELPA. Which documents should I read? If you could check out the http://bzr.savannah.gnu.org/r/emacs/elpa/ branch (or the bzr:// equivalent), there's a README in there. You can also prepare a tarball and Chong and I can help you convert it to a ELPA-style package, if you prefer. It should be easy :) Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-06-29 12:01 ` Ted Zlatanov @ 2011-06-29 17:33 ` SAKURAI Masashi 0 siblings, 0 replies; 93+ messages in thread From: SAKURAI Masashi @ 2011-06-29 17:33 UTC (permalink / raw) To: emacs-devel At Wed, 29 Jun 2011 07:01:39 -0500, Ted Zlatanov wrote: > : > SM> I have signed and received the assignment paper copy. I would learn > SM> the GNU ELPA. I'm going to check the emacs-devel threads about the > SM> ELPA. Which documents should I read? > > If you could check out the http://bzr.savannah.gnu.org/r/emacs/elpa/ > branch (or the bzr:// equivalent), there's a README in there. You can > also prepare a tarball and Chong and I can help you convert it to a > ELPA-style package, if you prefer. It should be easy :) Thank you for your advice. I will check it. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-06-29 5:31 ` SAKURAI Masashi 2011-06-29 12:01 ` Ted Zlatanov @ 2011-06-29 16:09 ` Chong Yidong 1 sibling, 0 replies; 93+ messages in thread From: Chong Yidong @ 2011-06-29 16:09 UTC (permalink / raw) To: SAKURAI Masashi; +Cc: emacs-devel SAKURAI Masashi <m.sakurai@kiwanami.net> writes: > I would learn the GNU ELPA. I'm going to check the emacs-devel threads > about the ELPA. Which documents should I read? See the Emacs Lisp Reference Manual's node on Packaging in trunk. ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-23 15:10 ` Ted Zlatanov 2011-05-23 15:42 ` SAKURAI Masashi @ 2011-05-23 15:45 ` Stefan Monnier 2011-05-25 2:02 ` Ted Zlatanov 1 sibling, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2011-05-23 15:45 UTC (permalink / raw) To: Ted Zlatanov; +Cc: emacs-devel > The idea from the beginning was that this is a true data type, not an > auxiliary library. At least deferred.el and fsm.el will use it, and I > am in favor of adding deferred.el to Emacs as I mentioned. I don't know of any package using deferred either, so it doesn't seem urgent to add to Emacs's core. I'd rather keep such things on ELPA for now until they prove their necessity. > I would rather not isolate its scope to just URL interactions because > rewriting url-future-* to future-* later will be annoying Maybe "annoying" but trivial to do. > and because it makes the package look like it has narrow utility. As long as no other package uses anything similar, it has narrow utility. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-23 15:45 ` Stefan Monnier @ 2011-05-25 2:02 ` Ted Zlatanov 2011-05-31 10:53 ` Ted Zlatanov 0 siblings, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-25 2:02 UTC (permalink / raw) To: emacs-devel [-- Attachment #1: Type: text/plain, Size: 823 bytes --] On Mon, 23 May 2011 12:45:51 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> The idea from the beginning was that this is a true data type, not an >> auxiliary library. At least deferred.el and fsm.el will use it, and I >> am in favor of adding deferred.el to Emacs as I mentioned. SM> I don't know of any package using deferred either, so it doesn't seem SM> urgent to add to Emacs's core. I'd rather keep such things on ELPA for SM> now until they prove their necessity. OK. >> I would rather not isolate its scope to just URL interactions because >> rewriting url-future-* to future-* later will be annoying SM> Maybe "annoying" but trivial to do. OK, I did as you asked. See attached, which has commentary, error handling, and ERT tests. I rewrote some trivial functions as defmacros. Thanks Ted [-- Attachment #2: url-future.el --] [-- Type: application/emacs-lisp, Size: 4850 bytes --] ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-25 2:02 ` Ted Zlatanov @ 2011-05-31 10:53 ` Ted Zlatanov 2011-05-31 16:55 ` Ted Zlatanov 0 siblings, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-31 10:53 UTC (permalink / raw) To: emacs-devel [-- Attachment #1: Type: text/plain, Size: 924 bytes --] On Tue, 24 May 2011 21:02:38 -0500 Ted Zlatanov <tzz@lifelogs.com> wrote: TZ> OK, I did as you asked. See attached, which has commentary, error TZ> handling, and ERT tests. I rewrote some trivial functions as defmacros. I'm trying to push and keep getting an error (break-lock didn't work): Using saved push location: /home/tzz/source/emacs/trunk/ Unable to obtain lock held by tzz at vcs-noshell [process #20860], acquired 1 second ago. See "bzr help break-lock" for more. bzr: ERROR: Could not acquire lock "(remote lock)": bzr+ssh://tzz@bzr.savannah.gnu.org/emacs/ I have to run and can't figure out how to fix it; can someone please commit the attached patch that adds url-future.el? Thanks Ted [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: url-future.patch --] [-- Type: text/x-diff, Size: 5419 bytes --] === modified file 'lisp/url/ChangeLog' --- lisp/url/ChangeLog 2011-05-29 02:45:03 +0000 +++ lisp/url/ChangeLog 2011-05-31 10:46:44 +0000 @@ -1,3 +1,7 @@ +2011-05-31 Teodor Zlatanov <tzz@lifelogs.com> + + * url-future.el: Add general futures facility. + 2011-05-29 Leo Liu <sdl.web@gmail.com> * url-cookie.el (url-cookie): Add option :named so that === added file 'lisp/url/url-future.el' --- lisp/url/url-future.el 1970-01-01 00:00:00 +0000 +++ lisp/url/url-future.el 2011-05-31 10:45:57 +0000 @@ -0,0 +1,126 @@ +;;; url-future.el --- general futures facility for url.el + +;; Copyright (C) 2011 Free Software Foundation, Inc. + +;; Author: Teodor Zlatanov <tzz@lifelogs.com> +;; Keywords: data + +;; This file is part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Make a url-future (basically a defstruct): +;; (make-url-future :value (lambda () (calculation goes here)) +;; :callback (lambda (future) (use future on success)) +;; :errorback (lambda (future &rest error) (error handler))) + +;; Then either call it with `url-future-call' or cancel it with +;; `url-future-cancel'. Generally the functions will return the +;; future itself, not the value it holds. Also the functions will +;; throw a url-future-already-done error if you try to call or cancel +;; a future more than once. + +;; So, to get the value: +;; (when (url-future-completed-p future) (url-future-value future)) + +;; See the ERT tests and the code for futher details. + +;;; Code: + +(eval-when-compile (require 'cl)) +(eval-when-compile (require 'ert)) + +(defstruct url-future callback errorback status value) + +(defmacro url-future-done-p (url-future) + `(url-future-status ,url-future)) + +(defmacro url-future-completed-p (url-future) + `(eq (url-future-status ,url-future) t)) + +(defmacro url-future-errored-p (url-future) + `(eq (url-future-status ,url-future) 'error)) + +(defmacro url-future-cancelled-p (url-future) + `(eq (url-future-status ,url-future) 'cancel)) + +(defun url-future-finish (url-future &optional status) + (if (url-future-done-p url-future) + (signal 'error 'url-future-already-done) + (setf (url-future-status url-future) (or status t)) + ;; the status must be such that the future was completed + ;; to run the callback + (when (url-future-completed-p url-future) + (funcall (or (url-future-callback url-future) 'ignore) + url-future)) + url-future)) + +(defun url-future-errored (url-future errorcons) + (if (url-future-done-p url-future) + (signal 'error 'url-future-already-done) + (setf (url-future-status url-future) 'error) + (setf (url-future-value url-future) errorcons) + (funcall (or (url-future-errorback url-future) 'ignore) + url-future errorcons))) + +(defun url-future-call (url-future) + (if (url-future-done-p url-future) + (signal 'error 'url-future-already-done) + (let ((ff (url-future-value url-future))) + (when (functionp ff) + (condition-case catcher + (setf (url-future-value url-future) + (funcall ff)) + (error (url-future-errored url-future catcher))) + (url-future-value url-future))) + (if (url-future-errored-p url-future) + url-future + (url-future-finish url-future)))) + +(defun url-future-cancel (url-future) + (if (url-future-done-p url-future) + (signal 'error 'url-future-already-done) + (url-future-finish url-future 'cancel))) + +(ert-deftest url-future-test () + (let* ((text "running future") + (good (make-url-future :value (lambda () (format text)) + :callback (lambda (f) (set 'saver f)))) + (bad (make-url-future :value (lambda () (/ 1 0)) + :errorback (lambda (&rest d) (set 'saver d)))) + (tocancel (make-url-future :value (lambda () (/ 1 0)) + :callback (lambda (f) (set 'saver f)) + :errorback (lambda (&rest d) + (set 'saver d)))) + saver) + (should (equal good (url-future-call good))) + (should (equal good saver)) + (should (equal text (url-future-value good))) + (should (url-future-completed-p good)) + (should-error (url-future-call good)) + (setq saver nil) + (should (equal bad (url-future-call bad))) + (should-error (url-future-call bad)) + (should (equal saver (list bad '(arith-error)))) + (should (url-future-errored-p bad)) + (setq saver nil) + (should (equal (url-future-cancel tocancel) tocancel)) + (should-error (url-future-call tocancel)) + (should (null saver)) + (should (url-future-cancelled-p tocancel)))) + +(provide 'url-future) +;;; url-future.el ends here ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-31 10:53 ` Ted Zlatanov @ 2011-05-31 16:55 ` Ted Zlatanov 0 siblings, 0 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-31 16:55 UTC (permalink / raw) To: emacs-devel On Tue, 31 May 2011 05:53:17 -0500 Ted Zlatanov <tzz@lifelogs.com> wrote: TZ> On Tue, 24 May 2011 21:02:38 -0500 Ted Zlatanov <tzz@lifelogs.com> wrote: TZ> OK, I did as you asked. See attached, which has commentary, error TZ> handling, and ERT tests. I rewrote some trivial functions as defmacros. TZ> I'm trying to push and keep getting an error (break-lock didn't work): TZ> Using saved push location: /home/tzz/source/emacs/trunk/ TZ> Unable to obtain lock held by tzz TZ> at vcs-noshell [process #20860], acquired 1 second ago. TZ> See "bzr help break-lock" for more. TZ> bzr: ERROR: Could not acquire lock "(remote lock)": bzr+ssh://tzz@bzr.savannah.gnu.org/emacs/ TZ> I have to run and can't figure out how to fix it; can someone please TZ> commit the attached patch that adds url-future.el? Apparently the push worked anyhow, though it looked to me like it didn't. I'm mystified. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines (was: more url-utils?) 2011-05-19 13:46 ` ELisp futures and continuations/coroutines (was: more url-utils?) Ted Zlatanov ` (2 preceding siblings ...) 2011-05-19 15:09 ` Thien-Thi Nguyen @ 2011-05-19 17:03 ` SAKURAI Masashi 2011-05-19 22:51 ` ELisp futures and continuations/coroutines Ted Zlatanov 3 siblings, 1 reply; 93+ messages in thread From: SAKURAI Masashi @ 2011-05-19 17:03 UTC (permalink / raw) To: tzz; +Cc: emacs-devel Hi, Ted I have just made an asynchronous library, deferred.el and concurrent.el. deferred.el : https://github.com/kiwanami/emacs-deferred/blob/master/README.markdown concurrent.el : https://github.com/kiwanami/emacs-deferred/blob/master/README-concurrent.markdown deferred.el is inspired by JSDeferred that comes from Mochikit.Async(JS) and Twisted(Python). The chain of asynchronous callbacks likes the continuation. Indeed, concurrent.el that is build on deferred.el, has the pseud-thread, the generator and the dataflow variable which may be similar to a "future" type. A sample code of concurrent.el https://github.com/kiwanami/emacs-deferred/blob/master/concurrent-sample.el Here is a demo for the networking and UI thread. (Sorry for machine translation...) http://translate.google.co.jp/translate?js=n&prev=_t&hl=ja&ie=UTF-8&layout=2&eotf=1&sl=ja&tl=en&u=http://d.hatena.ne.jp/kiwanami/20110413/1302709536 I have written some applications built on deferred.el and I found it works well. I think handling of asynchronous callbacks is getting important for the Emacs in the future. Because the Emacs interpreter is built on the single thread model (Node.js also employs the single thread model), the Emacs Lisp should have a way to write complicated asynchronous codes more easily. I would like to include deferred.el in the Emacs package. -- SAKURAI, Masashi (family, given) At Thu, 19 May 2011 08:46:21 -0500, Ted Zlatanov wrote: > > On Wed, 18 May 2011 19:05:57 -0300 Stefan Monnier <monnier@iro.umontreal.ca> wrote: > > SM> That's a good idea. Kind of like a future. > > Speaking of futures, can we have a general facility for those? > > 1) a real "future" type > > 2) a way to construct it and check if the value is available > > 3) process sentinel tie-in > > I'm sure much of this facility is either possible or already available > in ELisp, I just don't know the pieces and I think it would be very > convenient to provide a "future" type. WDYT? > > Similarly it would be very nice to provide continuations and coroutines > if those are not already possible. They don't need a top-level type > though, a lexical closure is sufficient I think. Please tell me how I'm > wrong :) > > Ted > > ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-19 17:03 ` ELisp futures and continuations/coroutines (was: more url-utils?) SAKURAI Masashi @ 2011-05-19 22:51 ` Ted Zlatanov 2011-05-20 15:49 ` SAKURAI Masashi 0 siblings, 1 reply; 93+ messages in thread From: Ted Zlatanov @ 2011-05-19 22:51 UTC (permalink / raw) To: emacs-devel On Fri, 20 May 2011 02:03:54 +0900 SAKURAI Masashi <m.sakurai@kiwanami.net> wrote: SM> I have just made an asynchronous library, deferred.el and concurrent.el. SM> deferred.el : https://github.com/kiwanami/emacs-deferred/blob/master/README.markdown SM> concurrent.el : https://github.com/kiwanami/emacs-deferred/blob/master/README-concurrent.markdown SM> deferred.el is inspired by JSDeferred that comes from Mochikit.Async(JS) and Twisted(Python). I looked at the code and it's pretty nice. It needs some small cleanup to be part of Emacs. SM> I have written some applications built on deferred.el and I found it works well. It's a good library, but maybe too complicated for general use. I don't know how the maintainers feel about anaphoric macros and chained futures. The resulting code, while neat, is IMO hard to understand if you don't understand the underlying macros. Also, the library does a lot more than futures, and I think it would be nice to separate just the futures (the `deferred' defstruct). But the way they are implemented currently, the queue implementation is implicit in the future definition itself. SM> I think handling of asynchronous callbacks is getting important for SM> the Emacs in the future. Because the Emacs interpreter is built on SM> the single thread model (Node.js also employs the single thread SM> model), the Emacs Lisp should have a way to write complicated SM> asynchronous codes more easily. I think with lexical closures Emacs is getting closer to true concurrency, which is better than simulating it in a single-threaded way. I like your approach, it's just (like fsm.el) that it's a very specific way of doing things that doesn't fit with the rest of ELisp code, so I don't think it should be the *standard* way to do futures or continuations. This is just my opinion; the Emacs maintainers should say what they think. SM> I would like to include deferred.el in the Emacs package. I'm in favor, it's a good library and more useful in the core than in the GNU ELPA. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-19 22:51 ` ELisp futures and continuations/coroutines Ted Zlatanov @ 2011-05-20 15:49 ` SAKURAI Masashi 2011-05-25 2:17 ` Ted Zlatanov 0 siblings, 1 reply; 93+ messages in thread From: SAKURAI Masashi @ 2011-05-20 15:49 UTC (permalink / raw) To: tzz; +Cc: emacs-devel At Thu, 19 May 2011 17:51:20 -0500, Ted Zlatanov wrote: > : > It's a good library, but maybe too complicated for general use. I don't > know how the maintainers feel about anaphoric macros and chained > futures. The resulting code, while neat, is IMO hard to understand if > you don't understand the underlying macros. I employed the anaphoric macros to simulate the method chains in conventional OOP languages or the "do" syntax in Haskell. I feel that it is not so good too. I would learn the better ideas. * JavaScript (JSDeferred): http.get("http://example.com/"). next(function(result) { alert(result); }); * Haskell: main = do x <- getContents putStr x * elisp (deferred.el): (deferred:$ (deferred:url-retrieve "http://www.gnu.org") (deferred:nextc it (lambda (buf) (insert (with-current-buffer buf (buffer-string))) (kill-buffer buf)))) > Also, the library does a lot more than futures, and I think it would be > nice to separate just the futures (the `deferred' defstruct). But the > way they are implemented currently, the queue implementation is implicit > in the future definition itself. Yes. The library deferred.el focuses on just supporting asynchronous callback programing. So, it is different from the "future" type that you mentions in some aspects. Although on the higher abstract layer, those ideas and implementations may be identical, the users like practical ones. It seems that many JavaScript developers like the word "deferred", and that the Java, C++ and other functional languages developers like "future". > I think with lexical closures Emacs is getting closer to true > concurrency, which is better than simulating it in a single-threaded > way. I like your approach, it's just (like fsm.el) that it's a very > specific way of doing things that doesn't fit with the rest of ELisp > code, so I don't think it should be the *standard* way to do futures or > continuations. I see. I think the developers who are familiar to JavaScript's deferred like deferred.el. > SM> I would like to include deferred.el in the Emacs package. > > I'm in favor, it's a good library and more useful in the core than in > the GNU ELPA. Thank you. I'm encouraged. -- SAKURAI, Masashi (family, given) ^ permalink raw reply [flat|nested] 93+ messages in thread
* Re: ELisp futures and continuations/coroutines 2011-05-20 15:49 ` SAKURAI Masashi @ 2011-05-25 2:17 ` Ted Zlatanov 0 siblings, 0 replies; 93+ messages in thread From: Ted Zlatanov @ 2011-05-25 2:17 UTC (permalink / raw) To: emacs-devel On Sat, 21 May 2011 00:49:09 +0900 SAKURAI Masashi <m.sakurai@kiwanami.net> wrote: SM> I employed the anaphoric macros to simulate the method chains in SM> conventional OOP languages or the "do" syntax in Haskell. I feel SM> that it is not so good too. I would learn the better ideas. Perhaps you can use macros to simplify things, so instead of (deferred:$ (deferred:url-retrieve "http://www.gnu.org") (deferred:nextc it (lambda (buf) (insert (with-current-buffer buf (buffer-string))) (kill-buffer buf)))) the user could say (when we're specifically working with URL retrieval) (deferred:do-url "http://www.gnu.org" ;; string implies url-retrieve ;; lambda implies "nextc it" so the following two are equivalent (lambda (buf) ...) (nextc it (lambda (buf) ...)) but this is just an idea. I don't mean to tell you how it should work and IMO it's usable as is. Other, more experienced Lisp programmers should tell you what they think because I'm just a beginner. Ted ^ permalink raw reply [flat|nested] 93+ messages in thread
end of thread, other threads:[~2011-06-29 17:33 UTC | newest] Thread overview: 93+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-05-14 10:32 more url-utils? joakim 2011-05-14 11:21 ` Lars Magne Ingebrigtsen 2011-05-14 11:42 ` joakim 2011-05-15 1:59 ` Lars Magne Ingebrigtsen 2011-05-14 20:42 ` Dimitri Fontaine 2011-05-15 14:26 ` Jason Rumney 2011-05-16 18:25 ` Ted Zlatanov 2011-05-16 19:03 ` Stefan Monnier 2011-05-16 19:17 ` Ted Zlatanov 2011-05-16 19:22 ` Lennart Borgman 2011-05-16 19:32 ` Ted Zlatanov 2011-05-16 19:33 ` Lennart Borgman 2011-05-16 19:55 ` Ted Zlatanov 2011-05-16 19:52 ` Julien Danjou 2011-05-16 20:18 ` Ted Zlatanov 2011-05-17 3:04 ` Stefan Monnier 2011-05-17 8:13 ` Julien Danjou 2011-05-16 19:53 ` Stefan Monnier 2011-05-16 21:07 ` joakim 2011-05-16 21:18 ` Ted Zlatanov 2011-05-16 21:21 ` Lennart Borgman 2011-05-16 21:58 ` joakim 2011-05-17 11:40 ` Lars Magne Ingebrigtsen 2011-05-17 13:34 ` Stefan Monnier 2011-05-14 13:21 ` Ted Zlatanov 2011-05-16 13:15 ` Stefan Monnier 2011-05-16 15:19 ` Tom Tromey 2011-05-16 15:45 ` Stefan Monnier 2011-05-16 17:04 ` joakim 2011-05-16 17:17 ` Lennart Borgman 2011-05-16 17:30 ` Stefan Monnier 2011-05-16 18:39 ` Julien Danjou 2011-05-15 13:34 ` Chong Yidong 2011-05-17 22:26 ` Ted Zlatanov 2011-05-18 0:11 ` Stefan Monnier 2011-05-18 2:14 ` Ted Zlatanov 2011-05-18 12:16 ` Stefan Monnier 2011-05-18 13:44 ` Ted Zlatanov 2011-05-18 14:09 ` Stefan Monnier 2011-05-18 14:43 ` Ted Zlatanov 2011-05-18 22:05 ` Stefan Monnier 2011-05-19 1:57 ` Ted Zlatanov 2011-05-19 2:28 ` Stefan Monnier 2011-05-19 10:28 ` Ted Zlatanov 2011-05-19 11:53 ` Stefan Monnier 2011-05-19 12:43 ` Ted Zlatanov 2011-05-19 13:28 ` Stefan Monnier 2011-05-19 13:35 ` Ted Zlatanov 2011-05-30 17:31 ` Lars Magne Ingebrigtsen 2011-05-30 19:09 ` Stefan Monnier 2011-05-30 19:38 ` Lars Magne Ingebrigtsen 2011-05-30 22:17 ` Stefan Monnier 2011-05-30 23:11 ` Lars Magne Ingebrigtsen 2011-05-31 1:26 ` Stefan Monnier 2011-05-31 10:15 ` Lars Magne Ingebrigtsen 2011-05-31 12:45 ` Stefan Monnier 2011-05-31 18:38 ` Lars Magne Ingebrigtsen 2011-05-19 14:11 ` joakim 2011-05-19 14:40 ` Stefan Monnier 2011-05-19 13:46 ` ELisp futures and continuations/coroutines (was: more url-utils?) Ted Zlatanov 2011-05-19 14:15 ` ELisp futures and continuations/coroutines Stefan Monnier 2011-05-19 14:16 ` joakim 2011-05-19 15:24 ` Ted Zlatanov 2011-05-19 15:09 ` Thien-Thi Nguyen 2011-05-19 15:31 ` Ted Zlatanov 2011-05-19 16:40 ` Thien-Thi Nguyen 2011-05-19 23:48 ` Ted Zlatanov 2011-05-20 1:23 ` Thien-Thi Nguyen 2011-05-20 4:18 ` Mohsen BANAN 2011-05-20 15:30 ` Ted Zlatanov 2011-05-20 15:29 ` Ted Zlatanov 2011-05-22 13:17 ` Thien-Thi Nguyen 2011-05-23 14:24 ` Ted Zlatanov 2011-05-23 14:59 ` Stefan Monnier 2011-05-23 15:10 ` Ted Zlatanov 2011-05-23 15:42 ` SAKURAI Masashi 2011-05-25 2:07 ` Ted Zlatanov 2011-05-26 0:23 ` SAKURAI Masashi 2011-06-03 13:59 ` SAKURAI Masashi 2011-06-03 16:06 ` Ted Zlatanov 2011-06-04 6:21 ` SAKURAI Masashi 2011-06-29 5:31 ` SAKURAI Masashi 2011-06-29 12:01 ` Ted Zlatanov 2011-06-29 17:33 ` SAKURAI Masashi 2011-06-29 16:09 ` Chong Yidong 2011-05-23 15:45 ` Stefan Monnier 2011-05-25 2:02 ` Ted Zlatanov 2011-05-31 10:53 ` Ted Zlatanov 2011-05-31 16:55 ` Ted Zlatanov 2011-05-19 17:03 ` ELisp futures and continuations/coroutines (was: more url-utils?) SAKURAI Masashi 2011-05-19 22:51 ` ELisp futures and continuations/coroutines Ted Zlatanov 2011-05-20 15:49 ` SAKURAI Masashi 2011-05-25 2:17 ` Ted Zlatanov
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).