-
Notifications
You must be signed in to change notification settings - Fork 177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Lwt_seq, adapted from Stdlib #836
Conversation
Nice! I wanted to create something like that some time ago but I put it aside. You could add An then, the main thing that could be added is a way to map from Should it be a simple The first approach looks straightforward to use, but the second plays well with the lazyness of Ideas? Comments? |
Thanks @zshipko. Agree with @raphael-proust that using the pre-allocated |
src/core/lwt_seq.ml
Outdated
let* seq1 = seq1 () in | ||
match seq1 with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let* seq1 = seq1 () in | |
match seq1 with | |
seq1 () >>= function |
I think all of the uses of let*
here can be simplified similarly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Not that it should impact this PR, but is there a plan to have match*
in OCaml soon?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Relevant PR: ocaml/ocaml#1955
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm ok with using the let
-operators. This is mostly a matter of style. Are there any strong opinions on the matter?
I guess the main reason to use >>=
instead of let*
would be to keep compatibility with old ocamls, but we're already >= 4.8
which is when the binds where introduced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My suggestion for removing the let*
uses in these places was because it avoids introducing a name that is immediately matched on, but I don't have a strong opinion either way :-)
I just pushed some new changes with I would still like to add some tests to help demonstrate the exception situation as @avsm mentioned |
Looking into it more closely, I think that the documentation should probably mention I'll draft some comment block that explains it. |
src/core/lwt_seq.ml
Outdated
(* the GNU Lesser General Public License version 2.1, with the *) | ||
(* special exception on linking described in the file LICENSE. *) | ||
(* *) | ||
(**************************************************************************) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even though nobody will bother with this realistically, we can't have a part of the code claiming to be distributed under a (modified) LGPL license in an otherwise MIT-licensed Lwt, which doesn't (and shouldn't) make an exception for it — especially if it sends people to a LICENSE
file that isn't present in Lwt.
I think the detailed authorship of this code needs to be addressed. My (uninformed) guess is that this code was originally written by @c-cube, and modified by @zshipko for Lwt. So, we should ask @c-cube for permission to distribute this variant of it in Lwt under the MIT license, in the same way as all the other Lwt code. In particular, we don't include the names of authors in each file, but rely on blame for detailed authorship history.
If @c-cube agrees, @zshipko, please change these license headers to match the ones in the rest of Lwt. If this code is indeed substantially @c-cube's, we can also express that using a Co-authored-by field in the commit, and including a note about where the code comes form in the commit's detailed message. @raphael-proust can then make sure that is preserved during the squash.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can probably just write all that in the message of a future commit in this PR, probably the same one that would change the license headers, and, again, @raphael-proust can move the Co-authored-by and the history message to the right place when squashing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll make sure that the squashed commit includes the relevant info from the commit message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use it with the MIT license as far as I'm concerned, and there's no need to list me as an author. If you start adapting large portions of oseq (which you should 😉) you can also port it with MIT but list me as a coauthor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @c-cube!
If you rebase this against the |
Just wanted to check in on this and see if there's anything I can do to push it along |
@zshipko I'll merge it soon (probably tomorrow). I've been a bit busy with other things so I've put the Lwt side on pause, but I'm resuming it this week. |
@zshipko I pushed two small commits on top of your branch. Please have a look and check whether they are ok. Don't hesitate to rollback some/all changes: they are mere suggestions. (Although I guess the commit for the changelog is not controversial in any way.) The MR looks generally good. I'll just open a thread to discuss |
val of_seq : 'a Seq.t -> 'a t | ||
(** Convert from ['a Stdlib.Seq.t] to ['a Lwt_seq.t]. | ||
This transformation is lazy, it only applies when the result is | ||
traversed. *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure which of_seq
we should have: the one currently in the MR, another, both?
Options:
- current code
val of_seq : 'a Seq.t -> 'a t
- Lwt-flipping
val of_seq : 'a Lwt.t Seq.t -> 'a t
The idea behind the Lwt-flipping of_seq
is as follows.
You can already have lwt-sequence with 'a Lwt.t Seq.t
. And as long as you are careful, you can consume the promises sequentially:
let rec iter_s f s =
match s () with
| Nil -> Lwt.return_unit
| Cons (p, s) ->
let* x = p in
let* () = f x in
iter_s f s
This works but you may accidentally step on your own feet and accidentally forget to wait for one promise to resolve before you start evaluating the next one.
The Lwt-flipping of_seq
allows you to go from the valid-but-error-prone form into the Lwt-specialised version.
Maybe we need both because this Lwt-flipping of_seq
is not as much as an inverse to to_seq
. Maybe we can have of_seq
as is, and we can have inject
(or some better name) for the Lwt-flipping of_seq
.
Ideas? Comments? Suggestions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current of_seq
implementation should probably stay as it is, but adding the Lwt-flipping version is a good idea.
of_seq_lwt
was mentioned above - that seems a little more clear thaninject
to me.
I will let you know when those changes are pushed.
src/core/lwt_seq.mli
Outdated
val to_seq : 'a t -> 'a Seq.t Lwt.t | ||
(** Convert from ['a Lwt_seq.t] to ['a Stdlib.Seq.t] *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is going to force all of the sequence cells in order to run the blocking actions, which is perhaps surprising given its name. We could call it all
or similar, but personally I think it's odd to support converting this structure back to a Seq.t
at all. I'd be in favour of removing this function altogether.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point, I'm not opposed to removing to_seq
I think to_seq doesn't make much sense.
Maybe there could be `to_list: 'a Lwt_seq.t -> 'a list Lwt.t`, which is
clearly materializing the whole sequence; returning a "lazy" view which
is actually fully materialized seems less useful imho.
|
Replacing |
(The PR already contains |
Alright, just pushed a commit that removes |
I added a small commit that adds a tiny bit of Lwt-specific documentation: it mentions promises and such. I think there's room to extend the tests and to factor things out there, but as a follow-up MR rather than additional commits in this one, just to make sure it progresses. @zshipko is it good for you? If so I'll merge and make sure there's the appropriate commit message as mentioned above. |
Thank you for adding that additional documentation, @raphael-proust - LGTM! |
Adds
Lwt_seq
, which mirrorsSeq
from the standard library but the callbacks return deferred values.Let me know if there's anything missing!