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

feat: add @math.(max|min)imum_by_key #1162

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

rami3l
Copy link
Contributor

@rami3l rami3l commented Oct 23, 2024

Mirrors Rust's max_by_key and min_by_key functions.

New Functions

  • math/algebraic.mbt: Added maximum_by_key function to return the element that gives the maximum value from the specified function.
  • math/algebraic.mbt: Added minimum_by_key function to return the element that gives the minimum value from the specified function.

Tests

  • math/algebraic_test.mbt: Added tests for the maximum_by_key and the minimum_by_key functions to verify their behavior with positive and negative integers.

Interface

  • math/math.mbti: Updated the module interface to include the new maximum_by_key and minimum_by_key functions.

Copy link

peter-jerry-ye-code-review bot commented Oct 23, 2024

Observations and Suggestions

  1. Type Annotation in Tests:

    • In the maximum_by_key and minimum_by_key tests, the assert_eq! macro is used without type annotations. While this might work in some contexts, it's good practice to include type annotations to avoid any potential runtime type mismatches.
    • Suggestion:
      assert_eq!(Int, @math.maximum_by_key(1, -2, abs), -2)
      assert_eq!(Int, @math.minimum_by_key(1, -2, abs), 1)
  2. Doc Comments Formatting:

    • The doc comments for maximum_by_key and minimum_by_key functions use backticks for code examples, which is correct. However, ensuring consistent formatting and including expected outputs can enhance readability and usefulness.
    • Suggestion:
      /// ```
      /// let abs = fn(n : Int) { if n < 0 { 0 - n } else { n } }
      /// print(@math.maximum_by_key(-2, 1, abs)) // output: -2
      /// print(@math.maximum_by_key(-2, 2, abs)) // output: 2
      /// ```
  3. Function Naming Convention:

    • The function names maximum_by_key and minimum_by_key follow a different naming convention compared to other functions in the file (e.g., maximum and minimum). Consistency in naming conventions can improve code readability and maintainability.
    • Suggestion:
      • Consider renaming maximum_by_key to max_by_key and minimum_by_key to min_by_key to align with the existing naming pattern.

Summary

  • Type Annotations: Ensure type annotations in test assertions for clarity and safety.
  • Doc Comments: Maintain consistent formatting and include expected outputs in doc comments for better documentation.
  • Naming Convention: Consider aligning the naming convention of new functions with existing ones for consistency.

These suggestions aim to enhance code readability, maintainability, and ensure consistent practices across the codebase.

@coveralls
Copy link
Collaborator

coveralls commented Oct 23, 2024

Pull Request Test Coverage Report for Build 3775

Details

  • 6 of 6 (100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.02%) to 83.772%

Totals Coverage Status
Change from base Build 3774: 0.02%
Covered Lines: 4326
Relevant Lines: 5164

💛 - Coveralls

@rami3l rami3l force-pushed the feat/cmp-by-key branch 5 times, most recently from c02892e to f8c47d1 Compare October 25, 2024 01:19
@bobzhang
Copy link
Contributor

Do we need these tiny functions? I think they are not particularly useful

@rami3l
Copy link
Contributor Author

rami3l commented Oct 25, 2024

Do we need these tiny functions? I think they are not particularly useful

I think it makes some business logic more readable, like the example below:

Before

let span l0 l1 =
  let first_byte, first_line =
    if l0.first_byte < l1.first_byte
    then l0.first_byte, l0.first_line
    else l1.first_byte, l1.first_line
  in
  let last_byte, last_line, file =
    if l0.last_byte < l1.last_byte
    then l1.last_byte, l1.last_line, l1.file
    else l0.last_byte, l0.last_line, l0.file
  in
  v ~file ~first_byte ~first_line ~last_byte ~last_line

After

pub fn TextLoc::span(self : TextLoc, other : TextLoc) -> TextLoc {
  let { first_byte, first_line, .. } = minimum_by_key(other, self, fn(it) { it.first_byte })
  let { file, last_byte, last_line, .. } = maximum_by_key(other, self, fn(it) { it.last_byte })
  { file, first_byte, last_byte, first_line, last_line }
}

@rami3l
Copy link
Contributor Author

rami3l commented Oct 25, 2024

Python does the same thing with the key parameter in max(arg1, arg2, *args, key=None).

Similarly, in the OCaml ecosystem, a slightly more heavyweight solution is available via Comparator.

@bobzhang
Copy link
Contributor

bobzhang commented Dec 8, 2024

@rami3l I think it is okay to have this util, but it does not belong to math package, can you create a cmp package like rust or Fun module like OCaml?

@rami3l
Copy link
Contributor Author

rami3l commented Dec 9, 2024

@rami3l I think it is okay to have this util, but it does not belong to math package, can you create a cmp package like rust or Fun module like OCaml?

@bobzhang Thanks for the feedback! In that case, however, should @math.(max|min) be moved elsewhere as well?

PS: I believe the Fun module in OCaml is for general operators on lambdas... cmp looks good to me.

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

Successfully merging this pull request may close these issues.

3 participants