-
Notifications
You must be signed in to change notification settings - Fork 17
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
tailOption
and initOption
#165
Comments
I agree that there are a couple of potentially useful methods here, but I don't think the name is quite right, since they shouldn't return |
What you expect as |
@jducoeur why shouldn't they return Option[Seq]? i'd expect them to so i can e.g. use them in a (Option-based) for-comprehension. |
You can, but is that really the useful behavior? While I don't strictly speaking object to an Option version, I'm hard-pressed to think of a time when I would want to use it. What I think I would more often want is a safe version of (But obviously, this is subjective.) |
@jducoeur in this context, not really. If it were returning something like |
I guess the deeper question is: what is the point of If you grant that |
I suppose, what actually bothers me is the documentation? val vector = Vector()
// Collection's "special" accessors
vector.head // Tells me it can throw
vector.headOption // Should never throw from signature and docs
vector.init // Throws but doesn't tell me
vector.last // Tells me it can throw
vector.lastOption // Should never throw from signature and docs
vector.tail // Throws but doesn't tell me
// Possibilities I see:
extension [A](vector: Vector[A])
// From signature, should never throw
def initOption: Option[Vector[A]] = if vector.isEmpty then None else Some(vector.init)
def tailOption: Option[Vector[A]] = if vector.isEmpty then None else Some(vector.tail)
// From name, should never throw
def initOrEmpty: Vector[A] = if vector.isEmpty then Vector.empty else vector.init
def tailOrEmpty: Vector[A] = if vector.isEmpty then Vector.empty else vector.tail
end extension
vector.initOption
vector.tailOption
vector.initOrEmpty
vector.tailOrEmpty
EDIT: I made a dumb typo and flipped the val tailOrEmpty = if vector.isEmpty then vector.tail else Vector.empty
// -- @julian-a-avar-c, 2024 I think my favorite implementation so far is |
No, this is not a good thing. If you want the whole list save the first element, safely, use Likewise with If |
@Ichoran I think it's useful to think in terms of If your thoughts are to tough it out and use In the case adding
Lastly and for completeness, I would like to acknowledge with you that I don't think anyone here is advocating for Let me know if any of this sounds appealing, and if I can be of help. |
I agree that for completeness But what I don't agree with is that someone reaching for I think we should structure the documentation to help people who are learning. However, I don't think we should structure the library to "help" people who are trying, because of lack of familiarity, to build from the parts they know functionality that already exists. Rather, we should help them learn the functionality that exists. (Note: The reason to use |
Ok... Full stop... Moving on... I'm aware of As a side note, I believe I suppose what I'm asking is: What are the reasons to avoid this design? And what are the reasons to add it? As I see it, there are only good things from |
In fact, I would say I'm advocating for |
If you're interested, and I'm suggesting here once more, perhaps if we wanted to more closely model the extension [A](vector: Vector[A])
def tailOnlyOption: Option[Vector[A]] = if vector.length < 2 then None else Some(vector.tail) That is to say, if there is 0 or 1 elements (no tail), return |
Part of learning a new language is getting used to the standard ways to do things. Maybe it makes more sense to you that I agree with you that one could define things differently. It's not insensible a priori. It just isn't how Scala works, and I don't agree that it's more intuitive in general. I mean, you could also argue that you should index from 1 in Scala instead of 0. Who starts counting at 0, anyway?! R and Matlab do, in fact, index from 1. But most languages, including Scala (and Java, and Python, and C/C++, and JavaScript) index from 0. If you wanted a new low-level operation So, some things can be made more intuitive within the context of the language, but mostly by making the patterns more regular. If you have If you make your own language or even your own library, you can make these decisions anew. But existing well-established regularities should be left alone, and the bar to add new variants should be quite high--mostly finding very common use cases that are only very awkwardly supported by the existing library. (There are a still a surprising number of these, despite the already-large library.)
But that has the behavior of |
I see, thank you for your responses. I suppose my vision was shortsighted. |
For symmetry. Once in a while I need them because the sequence might be empty.
Seq().tail
andSeq().init
throw errors. Ideally I want those two to be corrected and return an empty sequence, but I understand that might break backwards compatibility.One other alternative to these is
seq.drop(1)
andseq.dropRight(1)
, as they safely work as expected. However, I think addingtailOption
andinitOption
would bring the value of not having to remember they don't exist when I want to have the functionality of, "take the tail, but the sequence was empty".The text was updated successfully, but these errors were encountered: