Greetings people,
it's been a tick.
I've been toying with nim 1.0 and I was baffled to find out that I couldn't simply reverse a seq. It's such a common operation in wildly available in other languages, what gives?
You have, map, filter, reduce, etc. but not reverse? I had to ask.
cheers,
keyle.
It's available in algorithm not in sequtils (I think I tripped over it too once):
https://nim-lang.org/docs/algorithm.html#reverse%2CopenArray%5BT%5D%2CNatural%2CNatural
https://nim-lang.org/docs/algorithm.html#reversed,openArray[T]
Hmm, thank you.
And it's not queuable either, I can't do list.reverse().join() like I could with the rosetta reverse sample.
I'd recommend updating the rosetta code example to use the algorithm lib if that's the better way to do it.
I'm assuming you're talking about: https://rosettacode.org/wiki/Reverse_words_in_a_string#Nim
Look closely at that code and the 2 links I send.
You mentioned you can't do
list.reverse().join()
BUT! reverse() modifies the list in place(thus doesn't return anything). reversed() works fine, since it returns a new list and you can call join() on that.
Yes, I've read them and I changed my code to use reverse() as two separate lines...
I was commenting, albeit not clearly, on the fact that it's a loss from the method that allows function chaining (in terms of style), which I think it neat.
I was also mentioning that someone should look at updating the rosetta code to use the preferable solution of the algorithm lib.
Thanks for your time.
@kayle, possibly reversing seq's is not implemented in any of the current standard libraries because it is so easy to do writing it yourself.
You have, map, filter, reduce, etc. but not reverse?
These are a little trickier to implement that a simple reversal:
I recently needed to reverse a result string in place, so investigated the best way to do it. I ended up using the first method from rosetta code reversing a string in the first example, which is about as efficient as anything when one already has a "result" as a mutable (var) string. If one wanted a proc returning a reversal, the second example is just about as simple although requiring an allocation.
string's and seq's are really the same thing except that strings only contain char's; thus one could quickly write the following generic proc's to reverse seq's, either in-place as for the first proc or as a new version, as in the second:
proc reverse[T](s: var seq[T]) =
for i in 0 .. (s.high - 1) shr 1: swap(s[i], s[s.high - i])
proc reversed[T](s: seq[T]): seq[T] =
result = newSeq[T](s.len)
for i in 0 .. s.high: result[s.high - i] = s[i]
var s = @[ 1, 2, 3, 4, 5 ]; s.echo # original
s.reverse; s.echo # reversed in place
let ns = s.reversed; ns.echo # new copy reversed again
which outputs:
@[1, 2, 3, 4, 5]
@[5, 4, 3, 2, 1]
@[1, 2, 3, 4, 5]
and which you can play with on this Nim Playground.
Hardly seems worth importing a library for one of these and you could possibly even inline them to avoid the proc call!
possibly reversing seq's is not implemented in any of the current standard libraries because it is so easy to do writing it yourself.
I don't think that this is a good reason.
Some months ago I even voted for having even() and odd() in the standard lib, maybe as isOdd() and isEven().
I just like to have available what I need from time to time. I was even a bit angry when I noted some months ago that there seems to be no Inf for float32 available. And I am unhappy that for example https://github.com/StefanSalewski/gintro/blob/master/tests/combinatorics.nim from bright R. Behrends is not available by default.
Good reasons why something is not available by default may be that it is used really rarely only, that it may generate name conflicts, or that it is an expensive operation, which users may use too carelessly without noting that it is expensive. For the last point I am not sure, we have find for array for example, and that is fine if array is not too large.
I like outplace but I don't want x.reverse().outplace().join.outplace().
In any case, I think the reversed, joined, shuffled proc are bad.
They create a lot of intermediate memory allocations and then people will complain that we are slower than Python, Ruby, Javascript, ... when processing strings. Then someone will spend time working on an optimized implementation with in-place everything and we're back to C land.
I think we need either iterator chaining like Rust/zero-functional or a range-based API like C++/D to keep the nice chaining syntax without the inefficiencies of intermediate memory allocation.
I think we need either iterator chaining like (...) zero-functional
For those who are not familiar with it, take a look at: https://github.com/zero-functional/zero-functional
But whether you can avoid the copy or not depends on the operation, I don't see how e.g. sorted can be done without allocations and C++/D's solutions are effectively pointer-based so you pay the costs of wild aliasing. Rust uses its borrow checking to make it safe.
In-place everything is not "back to C land", it's still memory safe. But we can also leverage Nim's DSLs for this and I know you used this in the past too. With a DSL you get to see a much bigger picture and so optimizing the code is easier.
AFAIK, we can probably get something safe once we can store openarray in objects. I never used C++/D ranges but I assume they can't escape their scope.
Regarding copies, obviously I was thinking of map with potentially a final reduce and stretch goal: filter.
map without copies at minimum should be possible with sink overload with the new destructors because we could reuse the passed container in a destructive way.
As a recent adopter of Nim (but not a newcomer to programming), I have to say that neither outplace or re-implementing my own reverse/reversed for every project are intuitive/expected.
A decent standard library with a solid core of expected algorithms (and familiar naming of those algorithms) is one of the appealing aspects of Nim -- I'd urge the community to take this into consideration if the goal is to drive adoption.
Remember to use "search" on https://nim-lang.org/docs/lib.html.
Aside from your question, I think the algorithm module is a little bit wierd: only a few functions, and reverse is in it. In my humble opinion, reverse does not look like an algorithm. ^_^
I just remembered that we had a similar discussion some months ago:
Thanks for the responses.
Bringing it back to the original post, as a user, I fully expect the language or the standard lib of a high level language to do stuff like reverse() on a dynamic array out of the box. Odd and Even stuff is really easy with modulo support but I'd expect reversing lists to be there.
As a user, I want to be solving my own high level problems without having to think of the internals as much as possible.
cheers, keyle.