قالب وردپرس درنا توس
Home / IOS Development / Splitting a quick sequence in the head and tail – Ole Begemann

Splitting a quick sequence in the head and tail – Ole Begemann



A common pattern in functional programming languages ​​is to share a list in the head (the first element) and the tail (all remaining elements). For example, the x: xs pattern in Haskell matches a non-empty list and binds the head of the list to the variable x and the tail to xs .

Swift is not a functional language. It also has no built-in List type, nor a special synthetic matching syntax for collections.

Nevertheless, a sequence or collection splits into the head and the tail may sometimes be useful. For collections this is correct:

  extension     
      var    headAndTail :    [  head :    Element     tail : [1
9659011] subsequence
] guard la head = first other { return nil } return ( head dropFirst ()) } } if la ( firstLetter Rest ) = "Hello" . headAndTail { / / firstLetter: Character == "H" // rest: Substring == "ello" }

For sequences, it is harder because they are allowed to be single-pass sequences can only be iterated over once iteration consumes its items. Think of a network flow as an example. After you have read a change from the buffer, the operating system shuts it away. You can not tell it to start over.

One possible solution is to create an iterator to be read in the first item, then package current iterator status in a new AnySequence example:

  extension    Sequence    {
      ]    headAndTail :      head :    Element     tail : [19659005] AnySequence  <  Element    19659042]> )?    {19659017] var    iterators    =    makeIterator  () 
          cover [19659021] la    head    =    iterators .      [19659000]]    {   return    nil  } [19659020] la    tail    =    AnySequence    {[19659021] iterator  } 
          return    (  head     tail ) 
    } 
} 

This code works but it's not a nice generic solution, especially y for types that also match Collection . Packing of the tail in one AnySequence is a major performance kill and you can not use affordances of a collection of true SubSequence type.

You would be better off writing two extensions, one for Collection and one for Sequence to maintain the type SubSequence for collections. (And as we can see, this is also the preferred solution from Swift 5, but I'm coming to it.)

Keep the SubSequence Type

I could not find a general solution for Sequence which held SubSequence the type intact and correctly worked with single pass sequences. I thank Dennis Vennink to come up with a solution and share it with me . Here is his code (slightly modified by me for style):

  extension [19659000] Sequence    {
      var    headAndTail :    (  head : [19659011]] Element     tail :    subsection )    {
          was    first : ?? [19659000]  [19659000]]    nil 
          la    tail    =    drop  (  human :    {   element    in 
              if [19659024] first    ==    nil    {
                  first    =    item 
                  return    true 
            }                                     Otherwise    19659008]    [19659000]] [19659000]]   ]   ] 
        } 
          back    (  head     hale  trick is calling  Sequence.drop (while :)  who retains  SubSequence  the type for the tail, and then captures the first item inside the  drop (while :)  ] predicate closure using a captured local variable. Nicely done! 

Code of Goal Swift 4.2. It will break into Swift 5 because sequencdes will no longer have an associated SubSequence type, only collections (Swift Evolution proposal SE-0234).

This change has many advantages, but it means that we are no longer able to write generic algorithms that use SubSequence and work with Sequence and Collection at the same time.

Instead, we can put the right solution to

Collection

: 

  extension    Collection    {
      var    headAndTail :    (  ]  [19659000] [19659000]] [19659000]       :    Subsequent  19659021] First    Otherwise       Return    Nil  } 
          Return    (  Head     DropFirst  ()) 
     ]} [19659037]} 

If we find that we need the same functionality for Sequence also, we should add a separate extension using the new DropWhileSequence type as the return type for the tail head : head : Element tail ]: DropWhileSequence < Even > ) {
was first : ?? [19659000] [19659000]] nil
la tail = drop ( human : { element in
if first [19659023] == nil {
first = item
return true
} Other
false
}
})
cover la head = first [19659021] otherwise [19659008] {19659013] ] ] ]
return ( head tail )
}
}

The implementation is the same as above. Only the return type has been changed.)




Source link