Drop/skip the next i elements in the input source if possible.
Drop/skip the next i elements in the input source if possible.
Since dropping results in nothing the result can be ignored.
// results in a Processor[Seq[]] for { api <- input.processor _ <- api.drop(10) seq <- api.take(5) } yield seq
the number of elements to skip
the returned Processor can typically be ignored since it is a unit processor.
Ends the ProcessAPI.
Ends the ProcessAPI. Any attempts to take or drop will have no effect after the process is ended.
for { api <- input.processor _ <- repeatUntilEmpty seq <- api.take(5) if(seq contains 1) _ <- api.end } yield seq
Example takes 5 elements from the input source until it contains the value 1 then it ends the repeating and returns the seq.
The resulting Processor will be of type Processor[Iterator[Seq[A] ] ], even though there can only be one element, thus calling: result.traversable.headOption is likely the easiest method of obtaining the value from the Processor
Just a side note: This could be done with a LongTraversable with: traversable.sliding(5,5).filter(_ contains 1).headOption Note that you need to use headOption because you don't know if there are any elements in the resulting traversable, however the LongTraversable API would be difficult to use if you want to processes multiple input objects together
a Processor[Unit] and therefore the result can normally be ignored
End the processes if the predicate return true.
End the processes if the predicate return true. Any attempts to take or drop will have no effect after the process is ended.
for { api <- input.processor _ <- repeatUntilEmpty() seq <- input.take(5) _ <- input.endIf(_ contains 25) } yield seq
The Example takes 5 elements of the input until one of the sequences contains the number 25.
As a side note: This could be done using the LongTraversable API: traversable.sliding(5,5).takeWhile(i => !(i contains 25)) While this example can be done with the normal traversable API, this API is typically preferred when reading data from multiple interdependent sources.
the predi
a Processor[Unit] and therefore the result can normally be ignored
Read the sequence of characters from the current element in the input source if A are Char.
Read the sequence of characters from the current element in the input source if A are Char.
In practical terms the implicit portion of the method signature can be ignored. It is required to make the method type safe so that a method call to the method will only compile when the type of A is Char
flag to indicate whether the terminator should be discarded or kept
the method to use for determine where the line ends
a Processor containing the sequence of characters from the current element in the input source
Read the next element in the input source if possible.
Read the next element in the input source if possible.
If there is an element left in the input source a Processor containing that element will be returned, otherwise the returned processor will be empty.
Since next will return an empty processor it will terminate the looping in a for-comprehension and the resulting Processor could be an empty processor. This can be a problem when reading from multiple input sources. the opt method can be used to modify the returned processor so that it returns a Processor[Option[_]] that is never empty. COnsider the following examples
Example:
for { api1 <- input1.bytes.processor api2 <- input2.bytes.processor _ <- api1.repeatUntilEmpty() api1Next <- api.next next <- api2.next } println(api1Next) for { api1 <- input1.bytes.processor api2 <- input2.bytes.processor _ <- api1.repeatUntilEmpty() api1Next <- api.next nextOpt <- api2.next.opt } println(api1Next)
The two examples appear similar. The first example will print the bytes from input1 until input2 is empty. Where as in example 2 will print all of api1 irregardless of whether api2 is empty or not.
The reason is that in example 1 (next), next returns an empty processor when input2 is empty and thus the println is not executed. In example 2 the Processor is never empty it is either Some or None.
An empty processor if there are no more elements in the input source or a processor containing the next element in the input source.
if the process has a repeatUntilEmpty() method call, next.opt should be preferred over next. See repeatUntilEmpty for a more detailed description of why
Loops n times or until the provided input sources are all empty.
Loops n times or until the provided input sources are all empty.
This method is similar to repeatUntilEmpty except it limits the number of repetitions that can be performed.
the maximum number of loops
other input sources to monitor for empty before prematurely ending the loop. If this and otherProcessorAPIs are all empty then the looping will be ended
Create a Processor that simply repeats until this processor and all of the other input sources that are passed in are empty or ended.
Create a Processor that simply repeats until this processor and all of the other input sources that are passed in are empty or ended. Each repetition generates an integer that can be used to count the number of repetitions if desired.
other processors to empty (in addition to this) before ending the loop
A Processor containing a sequence of whatever elements are returned by the for-comprehension
repeatUntilEmpty can very easily result in infinite loops because it depends on the following components of the process/workflow correctly retrieving elements from the input source so that it eventually empties
The following examples are ways that one can create infinite loops (or loops that last up to Long.MaxValue):
for { processor1 <- input.bytes.processor processor2 <- input.bytes.processor processor1Loops <- processor1.repeatUntilEmpty() // if processor2 is emptied before processor1 there is an infinite loop because // this section will be the loop and since processor1 is not accessed here we have a loop // to be safer next1 should be in this section processor2Loops <- processor2.repeatUntilEmpty() next1 <- processor1.next.opt next2 <- processor2.next.opt } yield (next1, next2)
for { processor1 <- input.bytes.processor processor2 <- input.bytes.processor processor1Loops <- processor1.repeatUntilEmpty(processor2) next1 <- processor1.next // next.opt should be used here because this can cause // an infinite loop. if processor1 is empty and processor2 is not // next produces an empty processor so the next line will not be executed // next.opt would always produce an non-empty Processor and therefore // should be preferred over next next2 <- processor2.next } yield (next1, next2)
for { processor1 <- input.bytes.processor processor2 <- input.bytes.processor loops <- processor1.repeatUntilEmpty(processor2) if loops < 100 // this guard is dangerous because if there are more than 100 elements in either // processor1 or processor2 there is an infinite loop because next1 and next2 never get called next1 <- processor1.next.opt next2 <- processor2.next.opt } yield (next1, next2)
A safe implementation using repeatUntilEmpty should only execute methods that produce non-empty Processors or should be done with extreme care.
for { processor1 <- input.bytes.processor processor2 <- input.bytes.processor processor1Loops <- processor1.repeatUntilEmpty(processor2) option1 <- processor1.next.opt option2 <- processor2.next.opt next1 <- option1 next2 <- option2 } yield (next1, next2) }}}
Construct a sequence by taking up to i elements from the input source
Construct a sequence by taking up to i elements from the input source
the maximum number of elements to take
a Seq[A] consisting of the elements taken from the input source
Construct a sequence by taking elements from the input source until the function returns false or there are no more elements in the input source.
Construct a sequence by taking elements from the input source until the function returns false or there are no more elements in the input source.
the predicate that determines when to stop taking elements
a Seq[A] consisting of the elements taken from the input source