public static String describe(List<org.apache.iceberg.expressions.Expression> exprs) {
    return exprs.stream().map(Spark3Util::describe).collect(Collectors.joining(", "));
  }
@Test
  public void testDescribeExpression() {
    Expression refExpression = equal("id", 1);
    assertThat(Spark3Util.describe(refExpression)).isEqualTo("id = 1");

    Expression yearExpression = greaterThan(year("ts"), 10);
    assertThat(Spark3Util.describe(yearExpression)).isEqualTo("year(ts) > 10");

    Expression monthExpression = greaterThanOrEqual(month("ts"), 10);
    assertThat(Spark3Util.describe(monthExpression)).isEqualTo("month(ts) >= 10");

    Expression dayExpression = lessThan(day("ts"), 10);
    assertThat(Spark3Util.describe(dayExpression)).isEqualTo("day(ts) < 10");

    Expression hourExpression = lessThanOrEqual(hour("ts"), 10);
    assertThat(Spark3Util.describe(hourExpression)).isEqualTo("hour(ts) <= 10");

    Expression bucketExpression = in(bucket("id", 5), 3);
    assertThat(Spark3Util.describe(bucketExpression)).isEqualTo("bucket[5](id) IN (3)");

    Expression truncateExpression = notIn(truncate("name", 3), "abc");
    assertThat(Spark3Util.describe(truncateExpression))
        .isEqualTo("truncate[3](name) NOT IN ('abc')");

    Expression andExpression = and(refExpression, yearExpression);
    assertThat(Spark3Util.describe(andExpression)).isEqualTo("(id = 1 AND year(ts) > 10)");
  }