Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
Redesign
NonEmptyLazyList
to be maximally lazy #4504base: main
Are you sure you want to change the base?
Redesign
NonEmptyLazyList
to be maximally lazy #4504Changes from 9 commits
ef284ec
ad69065
3c5e564
d80d959
e948a1d
10f8c21
4f842eb
df8778e
5e6b46e
29d095b
46754d4
2bb52cf
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
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 doubt this method belongs here.
Prepending one
LazyList
to another one lazily is the job thatLazyList.Deferrer
seems to be doing already. I.e.:Anyway a method that only involves
LazyList
on both sides does not seem to be a part of theNonEmptyLazyList
DSL to me.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.
so this question is... tough. conceivably, one might build up a result something like as follows:
now, you could argue that you still don't need it, and can construct the
Maybe
instance later. which is true. but that seems uglier and less intuitive to me. would love to get thoughts from more people.Edit: this is example is awful, for reasons that I will explain in another comment below. I'm honestly ashamed to have written it
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.
Yeah, indeed, I would :)
Again just IMO: the entire
Maybe
does not seem that it should be a part ofNonEmptyLazyList
per se. Because it looks like a bunch of extension methods forLazyList
that simply helps to construct a newNonEmptyLazyList
out of it.For example, see
cats.syntax.ListSyntax
and its correspondingListOps.toNel
, etc.So perhaps it would make sense to consider creating a
cats.syntax.LazyListSyntax
which would provide all this functionality as a bunch of extension methods only.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 issue is,
NonEmptyLazyList.fromLazyList
evaluates the first state/element of theLazyList
, which is Bad™;NonEmptyList.fromList
does not have this concern as theList
is already fully evaluated. the intent behindMaybe
was to have a way to construct aNonEmptyLazyList
without evaluating any elements. now thatfromLazyListUnsafe
has been changed to be lazy,Maybe
isn't needed as much, though I maintain that it is still a useful tool. its design could perhaps use a bit more workshopping thoughThere 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've been sick for a week, so I haven't been able to address things, but I'm hopefully better enough to get back to this.
the reason we need some sort of wrapper around
LazyList
with a#:::
operator is that, despite it syntactically being a right-associative prepend operator,#:::
actually behaves semantically as a left-associative append operator.this also means that my example earlier was terrible, and the design of
Maybe
isn't ideal either. I really have been off my game recently.I'll re-evaluate and redesign this part of the API to be a bit more reasonable with this in mind
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.
Do we really need this overload with
NonEmptyLazyList
type if we already have another one that takesLazyList
? I am a bit concerned about this overload trick. Usually, overloaded method names are discouraged unless absolutely necessary. But it does not seem to be the case here, because prepending aNonEmptyLazyList
can be easily achieved with just the single method above that takesLazyList
only: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.
it would be weird to have
NonEmptyLazyList
be a second-class citizen of its own API. however, the meaning of the methods are identical, yielding no additional conceptual weight and making the API easier to use. additionally, it's not possible to accidentally use the wrong method either, as they are only the same after erasure. I don't personally see any issue with itThere 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.
But it pretty much corresponds to the way how other APIs are organized in Cats. See for example
NonEmptyList.concat
vsNonEmptyList.concatNel
, alsoNonEmptyVector.concat
vsconcatNev
, etc. Retrospectively, it would not be a problem to overloadconcat
everywhere in the way as you're proposing. But for some reason the decision was to avoid overloading and provide clearer separate names wherever possible. I personally support it because feel a bit sour about having any sort of "hacks and tricks" in code – they are usually easy to add but tend to turn into maintenance hell in long-term run.That said,
NonEmptyList
has the:::
which takes anotherNonEmptyList
, not justList
. Perhaps it is just a legacy of that particular class because it was the very firstNonEmpty*
one. Anyway, it is still not overloaded.