Oh I forgot newer container types in C++:

* AssociativeContainer: An AssociativeContainer must also be a Container. 
 It allows for lookup based on some arbitrary 'key' (type is defined by the 
container) instead of an index.  The elements must be ordered so iterators 
to the same identical container must always result in the same order.  This 
has no constraints on lookup speed so it could be constant, or it could be 
linear or worse. This is like an Elixir Keyword list.

* UnorderedAssociativeContainer:  An UnorderedAssociativeContainer must 
also be a Container.  It allows for lookup based on some arbitrary 'key' 
(type is defined by the container) instead of an index.  The elements are 
not ordered so iterators to the same identical container may result in 
different orders each time.  This has the constraint that lookup speed must 
be at work linear but is preferred that the average case is either constant 
or logarithmic.  This is like an Elixir Map.



On Tuesday, July 25, 2017 at 10:23:31 AM UTC-6, OvermindDL1 wrote:
>
> Just for more data points (not proposing anything), perhaps look at how 
> C++ handles iterables I'll only be referencing the immutable iterator types 
> or the types that can be immutable based on their contained types, I'll 
> also be using the C++ names for them rather than the more traditional 
> OCaml'y/Haskell'y or so names as C++'s is more expressive due to having 
> more 'types':
>
> * Iterator:  This defines something is an iterator, however it has no way 
> to actually iterate it, it is only a marker trait that says that something 
> is some type of iterator
>
> * InputIterator:  This is something that you can 'get' something out of, 
> then 'next' to the next element until it 'ends' (or does not end, it could 
> be infinite).  You cannot go back over an iteration, it is consume-once 
> thus it is read-once, and you cannot write an element, even of the slot 
> that you are in.  The only real Elixir/Erlang 'InputIterator' that I can 
> think of off the top of my mind is the process mailbox.
>
> * OutputIterator:  This is something that you can 'put' something in to, 
> then next to the next 'slot' to put something in to it as well.  You cannot 
> read from an element even of the slot that you are currently in nor can you 
> write to an element multiple times, only once.  The only real Elixir/Erlang 
> 'OutputIterator' that I can think of is sending a message to a process.
>
> * ForwardIterator:  Every ForwardIterator is also an InputIterator and/or 
> an OutputIterator (depending on its contained types), you can get/put and 
> next, however unlike InputIterator/OutputIterator you can read/write 
> from/to a slot multiple times and you can also hold a cursor to a given 
> slot to read/write from/to it again even after you have 'next'/iterated 
> past it.  You cannot iterate backwards from a given slot, only forwards. 
>  This would be like iterating through a list in Elixir/Erlang.
>
> * BidirectionalIterator:  Every BidirectionalIterator is also a 
> ForwardIterator, except you can also go backwards from a slot.  In 
> Elixir/Erlang this would be like a zipper structure.
>
> * RandomAccessIterator:  Every RandomAccessIterator is also a 
> BidirectionalIterator except that you can jump to any slot in *constant* 
> time via an index.  An Elixir equivalent would be like accessing a tuple.
>
>
>
> C++ also has traits that define if something is a type of container, these 
> are:
>
> * Container:  The base Container trait (do note, these are not C++ 
> classes, they are 'traits', if something implements the required functions 
> for their type then they are considered to fulfill a given 'trait', there 
> is no inheritence or anything of the sort).  This defines something that 
> 'manages' something else.  It has a way to acquire a ForwardIterator (or 
> anything else that implements a ForwardIterator, such as a 
> Bidirectionaliterator).  This is like an Elixir list or a map or really 
> anything that holds something.
>
> * ReversibleContainer: A ReversibleContainer must also be a Container.  It 
> adds the constraints that acquiring an iterator must return an iterator 
> that fulfills a Bidirectionaliterator in capability.  It also adds the 
> constraint that it must be possible to get an iterator that iterates over 
> the elements in reverse order.  This is like an Elixir zipper.
>
> * AllocatorAwareContainer:  An AllocatorAwareContainer must also be a 
> Container.  It is a container that creates it's own elements via a (either 
> passed in or internal) allocator function instead of the user supplying the 
> element.  This is like an Elixir Stream.
>
> * SequenceContainer:  A SequenceContainer must also be a Container.  It 
> adds the constraints that the returned iterator must be in a linear 
> arrangement, such as getting different iterators on the same container must 
> always result in the same order and in constant iteration time (thus that 
> 'next' is constant time).  This is like iterating over an Elixir List but 
> not a map.
>
> * ContiguousContainer:  A ContiguousContainer must also be a Container. 
>  It adds the constraint that the returned iterator must be of type 
> RandomAccessIterator, thus allowing for constant time element access.  This 
> is like an Elixir tuple.
>
>
> A given iterator can fulfill multiple even disjoint iterator traits, like 
> being both an input and an output iterator (in Elixir this would be like a 
> File access interface).
>
> A given container can fulfill multiple container traits, like being both a 
> SequenceContainer and a ContiguousContainer, which in Elixir would be a 
> tuple since it fulfills both requirements.
>
>
> Just putting it out there that there are a lot of different kinds of 
> Sequences, and even in C++ you cannot know if an iterator (or even a 
> container) is not 'infinite'.  Like take stdin/stdout in C++, those are 
> InputIterator and OutputIterator respectively, yet you do not know if 
> either 'end' until you next() on them and test (and 'next()ing' on the 
> stdin InputIterator may 'wait' in time until more input comes in for 
> example, and writing to an OutputIterator of stdout may 'wait' in time if 
> the buffer is full and the receiving pipe has not processed the buffered 
> data yet, which can also happen when sending/receiving message on the BEAM 
> as well).
>
>
>
> On Monday, July 24, 2017 at 4:37:41 PM UTC-6, [email protected] wrote:
>>
>> This is a good point. I was looking for an example of how these protocol 
>> changes could allow us to make some enumerables not allow negative access. 
>> No existing thing in the language is a good example, though, because we 
>> would break current behaviour.
>>
>> It does present the interesting option of adding an `infinite` boolean 
>> field, defaulting to false, to the Stream struct and having the 
>> exhaustiblity protocol function check that. Then stream constructors that 
>> are known to generate infinities like Stream.cycle could opt-in to erroring 
>> on negative access. Stream modifiers known to 'curb' the infinities could 
>> reset it to true. Ambiguous operations would leave it unmodified.
>>
>> My exhaustible impl attempt will come well after my take on 
>> Enumerable.fetch, so I'm not really thinking very hard about this yet––just 
>> spitballing. But definitely the intention is not to have exhaustible? do 
>> any work, merely allow Enumerable implementers outside of core to opt-out 
>> of negative integer access if they wish.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/8f47e8d8-df60-4a16-b756-866f19495ce2%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to