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

[Feature Request] add Iter::maximum, minimum #1498

Closed
illusory0x0 opened this issue Jan 16, 2025 · 8 comments
Closed

[Feature Request] add Iter::maximum, minimum #1498

illusory0x0 opened this issue Jan 16, 2025 · 8 comments

Comments

@illusory0x0
Copy link
Contributor

A possible implentation

// if self is empty, maxinum will panic
pub fn Iter::maximum[T : Compare](self : Iter[T]) -> T {
  let z = self.head().unwrap()
  let max = fn(x : T ,y : T ) { if (x > y) { x} else { y} }
  self.fold(max,init=z)
}
@Lampese
Copy link
Collaborator

Lampese commented Jan 16, 2025

@peter-jerry-ye
Copy link
Collaborator

peter-jerry-ye commented Jan 17, 2025

pub fn Iter::maximum[T : Compare](iter : Iter[T]) -> T? {
  let mut result = None
  for t in iter {
    match result {
      None => result = Some(t)
      Some(v) => if v > t { result = Some(v) }
    }
  }
  result
}

@illusory0x0
Copy link
Contributor Author

benchmark

Redundant comparisons inside the loop

Some(Benchmark Task [maximum] Count = 100
----------------------------------------
Average Time: 0.000267959s/per test
Max Time Per Test: 0.0004914s/per test
Min Time Per Test: 0.0002335s/per test
----------------------------------------)
Some(Benchmark Task [maximum_opt] Count = 100
----------------------------------------
Average Time: 0.000746178s/per test
Max Time Per Test: 0.0010776s/per test
Min Time Per Test: 0.0006784s/per test
----------------------------------------)
Total tests: 1, passed: 1, failed: 0.
///|
pub fn maximum[T : Compare](xs : Iter[T]) -> T {
  let z = xs.head().unwrap()
  let max = fn(x : T, y : T) { if x > y { x } else { y } }
  xs.fold(max, init=z)
}

///|
pub fn maximum_opt[T : Compare](iter : Iter[T]) -> T? {
  let mut result = None
  for t in iter {
    match result {
      None => result = Some(t)
      Some(v) => if v > t { result = Some(v) }
    }
  }
  result
}

test {
  let crti = @bm.Criterion::new()
  let sample : Array[Int] = @quickcheck.samples(100000)
  crti.add(
    @bm.Task::new(
      "maximum",
      fn() { maximum(sample.iter()) |> ignore },
      count=100,
    ),
  )
  crti.add(
    @bm.Task::new(
      "maximum_opt",
      fn() { maximum_opt(sample.iter()) |> ignore },
      count=100,
    ),
  )
  let result = crti.run()
  println(result["maximum"])
  println(result["maximum_opt"])
}

@illusory0x0
Copy link
Contributor Author

we can improve it

pub fn maximum_opt[T : Compare](xs : Iter[T]) -> T? {
  match xs.peek() {
    Some(z) => {
      let max = fn(x : T, y : T) { if x > y { x } else { y } }
      xs.fold(max, init=z) |> Some
    }
    None => None
  }
}

@peter-jerry-ye
Copy link
Collaborator

Do not run Iter twice.

@illusory0x0
Copy link
Contributor Author

illusory0x0 commented Jan 19, 2025

pub fn Iter::tap[T](self : Iter[T], f : (T) -> Unit) -> Iter[T]

Why we need this API? I think user can cascade to perform a series operations

pub fn cascade[T](fs : Array[(T) -> Unit]) -> (T) -> Unit {
  fn (x : T) {
    for f in fs {
      f(x)
    }
  }
}

other Iter::methods are almost pure functions

@illusory0x0
Copy link
Contributor Author

I think we need to wait for HKT(higher kinded types) language features

https://discuss.moonbitlang.com/t/generic-traits-not-supported/214

@peter-jerry-ye
Copy link
Collaborator

There’s nothing to do with tap or HKT. Iter may be used to encapsulate a data source that can only be consumed once, such as strings from http body or websocket. The conversion process may also introduce side effects. We are not writing purely functional programming here.

As of tap, it has nothing to do with cascading operation either.

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

No branches or pull requests

3 participants