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

Refactor collections::list #12348

Merged
merged 18 commits into from
Feb 28, 2014
Merged

Refactor collections::list #12348

merged 18 commits into from
Feb 28, 2014

Conversation

brunoabinader
Copy link
Contributor

This PR includes:

  • Create an iterator for List<T> called Items<T>;
  • Move all list operations inside List<T> impl;
  • Removed functions that are already provided by Iterator trait;
  • Refactor on len() and is_empty using Container trait;
  • Bunch of minor fixes;

A replacement for using @ is intended, but still in discussion.

Closes #12344.

@brunoabinader
Copy link
Contributor Author

@alexcrichton r? :-)

@bill-myers
Copy link
Contributor

It seems to me any/find/etc. should be just removed, since one can use list.iter().any() and similar instead.

@@ -10,170 +10,164 @@

//! A standard, garbage-collected linked list.


pub type BoxedList<T> = @List<T>;
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure that this is the right use of a typedef. @List is smaller and more concise to write, and it is also more clear about how the list is built.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The intention here is to reduce usage of @list as I'm planning to replace it with Rc - do you believe it is still worth?

Copy link
Member

Choose a reason for hiding this comment

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

I don't think an alias is necessary here in either case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, removing then.

@brunoabinader
Copy link
Contributor Author

So here goes a rough list of things fixed since first attempt:

  • Removed iterator-based helper functions when already provided by Iteratortrait;
  • Removed BoxedList<T> public type (using raw @List<T>instead);
  • s/BoxedListIterator/Items/;
  • Removed lifetime parameter 'a;
  • len() and is_empty() are now provided using Containertrait;
  • Bunch of test fixes;
  • Replaced fail!() calls with Option<T> return;
  • s/push()/unshift()/

@brunoabinader
Copy link
Contributor Author

@alexcrichton, about having iter() for List<T> instead of BoxedListOps<T>, I've created a prototype in https://gist.github.com/brunoabinader/9139223 with some considerations:

On Items<T>, next cannot be @List<T> because &self cannot move out of its dereference in iter(). Because we're using a reference, a lifetime parameter is required. Also, because head in next() cannot move out if its dereference, T deriving Clone is required.

}
};
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Hm, I'm not sure how feasible this list will be if it require that its elements be clone-able. This also means that every time you get the length of the list you clone every object in the list!

You're going to want to return &'a T from this iterator so you can remove the Clone bound, which may mean that you need to store &'a List instead of @List like I had originally hoped.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Replacing Option<T> with Option<&'a T> on next()gives the following compilation error because of different signatures between Iterator's trait and this:

/Users/bruno.d/Work/rust/src/libcollections/list.rs:32:5: 40:6 error: method `next` has an incompatible type: expected type parameter but found &-ptr
/Users/bruno.d/Work/rust/src/libcollections/list.rs:32     fn next(&'a mut self) -> Option<&'a T> {
/Users/bruno.d/Work/rust/src/libcollections/list.rs:33         match *(self.current) {
/Users/bruno.d/Work/rust/src/libcollections/list.rs:34             Cons(ref value, ref next) => {
/Users/bruno.d/Work/rust/src/libcollections/list.rs:35                 self.current = *next;
/Users/bruno.d/Work/rust/src/libcollections/list.rs:36                 Some(value)
/Users/bruno.d/Work/rust/src/libcollections/list.rs:37             },

Copy link
Member

Choose a reason for hiding this comment

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

It does indeed, you'll need to add a lifetime parameter to the struct:

pub struct Items<'a, T> { next: &'a List<T> }

@liigo
Copy link
Contributor

liigo commented Feb 25, 2014

iter should be named items, I think
2014年2月25日 下午9:06于 "Bruno de Oliveira Abinader" <notifications@github.com

写道:

Fixes since last iteration:

  • Removed BoxedLisOps: Now all functions are based on List
  • Removed foldl() in favor of iter().fold()
  • Removed each() in favor of for x in list.iter()
  • Make head() use lifetime parameter 'a - avoids clone()
  • Make len() use iter().len() internally
  • Bunch of minor fixes


Reply to this email directly or view it on GitHubhttps://github.com//pull/12348#issuecomment-36004998
.

@brunoabinader
Copy link
Contributor Author

Fixes since last iteration:

  • Removed BoxedLisOps: Now all functions are based on List<T>
  • Removed foldl() in favor of iter().fold()
  • Removed each() in favor of for x in list.iter()
  • Make head() use lifetime parameter 'a - avoids clone()
  • Make len() use iter().len() internally
  • Bunch of minor fixes (>100 column lines, rebase hell, etc)

@brunoabinader
Copy link
Contributor Author

@liigo the iterator struct is called Items<T>, iter() refers to the function in List<T> that generates them.

@brunoabinader
Copy link
Contributor Author

The build error seems unrelated to this PR:

/home/travis/build/mozilla/rust/src/rustllvm/PassWrapper.cpp:169:47: error: no
      member named 'F_Binary' in namespace 'llvm::sys::fs'
  raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_Binary);
                                     ~~~~~~~~~^

tl
}
Nil => return false
impl<'a, T> List<T> {
Copy link
Member

Choose a reason for hiding this comment

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

Instead of putting the lifetime parameter at the top of the impl block, you can place it on the individual functions below as fn foo<'a>(&'a self) -> ....

You can then merge this impl block with the one below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ack :-)

@alexcrichton
Copy link
Member

This is looking great, nice work! Before committing, this'll need to squash some of the commits together, but that can wait until review is done.

@bill-myers
Copy link
Contributor

The Nil/Cons construction seems to duplicate Option.

What about defining List equivalently as:

struct Cons<T>
{
    head: T,
    tail: ~Option<Cons<T>>
}

type List<T> = Option<Cons<T>>;

Or ideally with this more natural representation:

struct Cons<T>
{
    head: T,
    tail: Option<~Cons<T>>
}

type List<T> = Option<~Cons<T>>;

(or using a tuple struct instead of with head/tail fields)

Note that also the current representation, equivalent to the first snippet, is very weird, since it starts the list with an inline element, terminates with a ~Nil.

This means that it passes data by value, requiring an explicit copy to prepend an element to the list due to the need to box the Cons and requires an explicit tag for the Nil vs Cons discriminator rather than being able to use the Option null pointer optimization.

It's definitely not how one would naturally implement a singly linked list in C, for example, while the second code snippet in this comment is the natural representation where an empty list is just a null pointer.

@eddyb
Copy link
Member

eddyb commented Feb 26, 2014

This definition should also be possible, for the second snippet above (and I remember mentioning it a couple times in the past, on IRC):

struct Cons<T> {
    head: T,
    tail: List<T>
}
type List<T> = Option<~Cons<T>>;

@brunoabinader
Copy link
Contributor Author

@alexcrichton, @bill-myers, @eddyb: I want to postpone modifying how List<T> is implemented internally until we properly discuss this and agree upon a better choice. What do you guys think?

@brunoabinader
Copy link
Contributor Author

Fixes since last iteration:

  • Using @alexcrichton's simpler logic for list::from_vec();
  • Moved lifetime parameter 'a to function signature for list::iter() and list::head();

ret
if isr_br == br { region = Some(isr_r); break; }
};
region.unwrap()
}
Copy link
Member

Choose a reason for hiding this comment

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

This change seems unrelated to the list changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Initially I've modified the code to replace list::each() with a for isr in self.iter() statement. But then I ended up with a refactor to simplify get_and_find_region::{get,find}() code. I can separate this if it seems necessary.

@alexcrichton
Copy link
Member

This looks good to me, I don't think it needs 21 commits, but with some squashings I'll r+

@brunoabinader
Copy link
Contributor Author

Ok, so I squashed a few commits and the # of commits is now down to 18.

bors added a commit that referenced this pull request Feb 28, 2014
…ry, r=alexcrichton

This PR includes:
- Create an iterator for ```List<T>``` called ```Items<T>```;
- Move all list operations inside ```List<T>``` impl;
- Removed functions that are already provided by ```Iterator``` trait;
- Refactor on ```len()``` and ```is_empty``` using ```Container``` trait;
- Bunch of minor fixes;

A replacement for using @ is intended, but still in discussion.

Closes #12344.
@bors bors merged commit 4da6d04 into rust-lang:master Feb 28, 2014
@brunoabinader brunoabinader deleted the libcollections-list-refactory branch February 28, 2014 11:58
flip1995 pushed a commit to flip1995/rust that referenced this pull request Feb 26, 2024
Remove `clippy_utils::get_parent_node`

Since it's forwarding to a single method it seems reasonable to use that one directly instead

changelog: none
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.

Provide iterator-based approach for collections::list
6 participants