Skip to content
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

feat: implement last and lastOption operators #26

Merged
merged 1 commit into from
Oct 30, 2023

Conversation

geminicaprograms
Copy link
Contributor

@geminicaprograms geminicaprograms commented Oct 26, 2023

The lastOption operator returns the last element in Source wrapped in Some or None in case when source is empty. Note that this is a terminal operation for source e.g.:

  Source.empty[Int].lastOption()  // None
  val s = Source.fromValues(1, 2)
  s.lastOption()                  // Some(2)
  s.receive()                     // ChannelClosed.Done

The last operator returns the last element in Source or throws NoSuchElementException in case when it is empty. In case when receive() fails with exception then this exception is re-thrown. It is also a terminal operation e.g.:

  Source.empty[Int].last()        // throws NoSuchElementException("cannot obtain last from an empty source")
  val s = Source.fromValues(1, 2)
  s.last()                        // 2
  s.receive()                     // ChannelClosed.Done

Note that ChannelClosedException.Error was improved to contain cause exception (if available).

def lastOption(): Option[T] =
supervised {
var value: Option[T] = None
repeatUntil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: In other operators we're using repeatWhile, which is similar, just with the condition inverted. I think we could use repeatWhile here as well for consistency.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤷‍♂️ but turned to repeatWhile

@@ -565,6 +565,63 @@ trait SourceOps[+T] { this: Source[T] =>
case ChannelClosed.Error(r) => throw r.getOrElse(new NoSuchElementException("getting head failed"))
case t: T @unchecked => t
}

/** Returns the last element from this source wrapped in [[Some]] or [[None]] when the source is empty. Note that `lastOption` is a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: According to the scaladoc style guide, please use "this source" instead of "[the] source" throughout the scaladoc. Also applies to the scaladoc for last.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

* @return
* A `Some(last element)` if source is not empty or `None` otherwise.
* @throws ChannelClosedException.Error
* When [[receive]] fails.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: receive (the function) is an implementation detail that the user might not be aware of. How about rephrasing this like "When receiving an element from this source fails."? Also applies to last

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

* }
* }}}
*/
def last(): T = lastOption().getOrElse(throw new NoSuchElementException("cannot obtain last from an empty source"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Please use "last element" insted of "last" in the error message.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

The `lastOption` operator returns the last element in `Source` wrapped in
`Some` or `None` in case when source is empty. Note that this is a terminal
operation for source e.g.:

  Source.empty[Int].lastOption()  // None
  val s = Source.fromValues(1, 2)
  s.lastOption()                  // Some(2)
  s.receive()                     // ChannelClosed.Done

The `last` operator returns the last element in `Source` or throws
`NoSuchElementException` in case when it is empty. In case when `receive()`
fails then `ChannelClosedException.Error` exception is thrown. It is also
a terminal operation e.g.:

  Source.empty[Int].last()        // throws NoSuchElementException("cannot obtain last element from an empty source")
  val s = Source.fromValues(1, 2)
  s.last()                        // 2
  s.receive()                     // ChannelClosed.Done

Note that ChannelClosedException.Error was improved to contain `cause`
exception (if available).
@geminicaprograms geminicaprograms merged commit 2cde6cd into master Oct 30, 2023
@geminicaprograms geminicaprograms deleted the feat_lastOption_last branch October 30, 2023 12:41
geminicaprograms added a commit that referenced this pull request Oct 30, 2023
….scala` (#28)

The following comments were applied:
* use supervised instead of scoped
* use toThrowable instead of ad-hoc exception creation
* don't catch exceptions in headOption
* also fixed comments about the source and receive function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants