/*
* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* This source file is part of the Cangjie project, licensed under Apache-2.0
* with Runtime Library Exception.
*
* See https://cangjie-lang.cn/pages/LICENSE for license information.
*/
// The Cangjie API is in Beta. For details on its capabilities and limitations, please refer to the README file.
/**
* @file
*
* Operate on each item of an iteratable object.
*/
package std.collection
/**
* This func reduce is calculated from left to right using the first value as initial value.
*
* @param operation This is the callback function that executes each value in Iterator.
* @return (Iterable<T>) -> Option<T> An iteration function accept an Iterable as its input.
*
*/
@Frozen
public func reduce<T>(operation: (T, T) -> T): (Iterable<T>) -> Option<T> {
return {
it: Iterable<T> =>
var itt = it.iterator()
var result: T = itt.next() ?? return None
while (let Some(value) <- itt.next()) {
result = operation(result, value)
}
return result
}
}
/**
* This func fold is calculated from left to right using the specified initial value.
*
* @param initial This is initial value.
* @param operation This is the callback function that executes each value in Iterator.
* @return (Iterable<T>) -> R An iteration function accept an Iterable as its input.
*
*/
public func fold<T, R>(initial: R, operation: (R, T) -> R): (Iterable<T>) -> R {
return {
it: Iterable<T> =>
var result: R = initial
for (item in it) {
result = operation(result, item)
}
return result
}
}
/**
* This func isEmpty is used to check whether Iterable<T> is empty.
*
* @param it An Iteratable.
* @return Bool Whether the Iterable is empty.
*
*/
public func isEmpty<T>(it: Iterable<T>): Bool {
return match (it.iterator().next()) {
case None => true
case _ => false
}
}
/**
* This func count is used to count the number of Iterable<T>.
*
* @param it An Iteratable.
* @return Int64 The number of the Iterable.
*
*/
public func count<T>(it: Iterable<T>): Int64 {
var count: Int64 = 0
for (_ in it) {
count++
}
return count
}
/**
* This func contains is used to check whether Iterable<T> contains a specified element.
*
* @param element The specified element.
* @return (Iterable<T>) -> Bool An iteration function accept an Iterable as its input.
*
*/
public func contains<T>(element: T): (Iterable<T>) -> Bool where T <: Equatable<T> {
return {
it: Iterable<T> =>
for (item in it) {
if (item == element) {
return true
}
}
return false
}
}
/**
* This func max is used to find the maximum value of Iterable<T>.
*
* @param it An Iteratable.
* @return Option<T> The maximum value.
*
*/
public func max<T>(it: Iterable<T>): Option<T> where T <: Comparable<T> {
var result: Option<T> = None
for (item in it) {
match (result) {
case Some(value) =>
if (item > value) {
result = Some(item)
}
case _ => result = Some(item)
}
}
return result
}
/**
* This func min is used to find the minimum value of Iterable<T>.
*
* @param it An Iteratable.
* @return Option<T> The minimum value.
*
*/
public func min<T>(it: Iterable<T>): Option<T> where T <: Comparable<T> {
var result: Option<T> = None
for (item in it) {
match (result) {
case Some(value) =>
if (item < value) {
result = Some(item)
}
case _ => result = Some(item)
}
}
return result
}
/**
* This func all is used to check whether all elements pass the test.
*
* @param predicate The function used to test each element.
* @return (Iterable<T>) -> Bool An iteration function accept an Iterable as its input.
*
*/
public func all<T>(predicate: (T) -> Bool): (Iterable<T>) -> Bool {
return {
it: Iterable<T> =>
for (item in it) {
if (!predicate(item)) {
return false
}
}
return true
}
}
/**
* This func any is used to check that at least one element passes the test.
*
* @param predicate The function used to test each element.
* @return (Iterable<T>) -> Bool An iteration function accept an Iterable as its input.
*
*/
public func any<T>(predicate: (T) -> Bool): (Iterable<T>) -> Bool {
return {
it: Iterable<T> =>
for (item in it) {
if (predicate(item)) {
return true
}
}
return false
}
}
/**
* This func none is used to check whether all elements fail the test.
*
* @param predicate The function used to test each element.
* @return (Iterable<T>) -> Bool An iteration function accept an Iterable as its input.
*
*/
public func none<T>(predicate: (T) -> Bool): (Iterable<T>) -> Bool {
return {
it: Iterable<T> =>
for (item in it) {
if (predicate(item)) {
return false
}
}
return true
}
}
/**
* This func first is used to get the first element of the Iterator.
*
* @param it An Iteratable.
* @return Option<T> The first element.
*
*/
public func first<T>(it: Iterable<T>): Option<T> {
return it.iterator().next()
}
/**
* This func last is used to get the last element of the Iterator.
*
* @param it An Iteratable.
* @return Option<T> The last element.
*
*/
public func last<T>(it: Iterable<T>): Option<T> {
var result: Option<T> = None
for (item in it) {
result = Some(item)
}
return result
}
/**
* This func at function is used to get the specified index element of the iterator.
*
* @param n The specified index.
* @return (Iterable<T>) -> Option<T> An iteration function accept an Iterable as its input.
*
*/
public func at<T>(n: Int64): (Iterable<T>) -> Option<T> {
return {
it: Iterable<T> =>
if (n < 0) {
return None
}
var i: Int64 = 0
for (item in it) {
if (i == n) {
return Some(item)
}
i++
}
return None
}
}
/**
* This func forEach function is used to perform a specific function on each element of Iterable.
*
* @param action The function executed by each element.
* @return (Iterable<T>) -> Unit An iteration function accept an Iterable as its input.
*
*/
public func forEach<T>(action: (T) -> Unit): (Iterable<T>) -> Unit {
return {
it: Iterable<T> => for (item in it) {
action(item)
}
}
}