函数式编程函数

Avatar of Kitty Giraudel
Kitty Giraudel

对于库开发者和框架构建者来说,拥有几个额外的函数来动态地将函数应用于列表中的项目可能会派上用场。以下是受 JavaScript 和 PHP 等价物启发,在 Sass 中实现的 4 个函数。

walk()

walk() 函数将给定的函数应用于列表中的每个项目。

/// Apply `$function` with `$args` to each item from `$list`.
/// @author Kitty Giraudel
/// @param {List} $list - List of items
/// @param {String} $function - Function to apply to every item from `$list`
/// @param {Arglist} $args - Extra arguments to pass to `$function`
/// @return {List}
/// @throw There is no `#{$function}` function.
@function walk($list, $function, $args...) {
  @if not function-exists($function) {
    @error "There is no `#{$function}` function.";
  }
  
  @for $i from 1 through length($list) {
    $list: set-nth($list, $i, call($function, nth($list, $i), $args...));
  }
  
  @return $list;
}

用法

walk {
  walk: walk(red green blue, invert);
  walk: walk(red green blue, lighten, 20%);
  walk: walk(2 4 6 8 10, sqrt);
}
walk {
  walk: cyan #ff7fff yellow;
  walk: #ff6666 #00e600 #6666ff;
  walk: 1.41421 2 2.44949 2.82843 3.16228;
}

some()

some() 函数返回列表中是否有一些项目通过给定的测试(作为函数)。

/// Return whether some items from `$list` passed `$function` test.
/// @author Kitty Giraudel
/// @param {List} $list - List of items
/// @param {String} $function - Function to run on every item from `$list`
/// @param {Arglist} $args - Extra arguments to pass to `$function`
/// @return {Boolean}
/// @throw There is no `#{$function}` function.
@function some($list, $function, $args...) {
  @if not function-exists($function) {
    @error "There is no `#{$function}` function.";
  }
  
  @each $item in $list {
    @if call($function, $item, $args...) {
      @return true;
    }
  }
  
  @return false;
}

用法

some {
  some: some(round ceil floor, function-exists);
  some: some(round ceil unknown, function-exists);
  some: some(completely unknown function, function-exists);
  
  some: some(4px 10px 20px, comparable, 42px);
  some: some(4px 10% 20px, comparable, 42%);
  some: some(4px 10px 20px, comparable, 42%);
}
some {
  some: true;
  some: true;
  some: false;
  some: true;
  some: true;
  some: false;
}

every()

every() 函数返回列表中是否每个项目都通过给定的测试(作为函数)。

/// Return whether all items from `$list` passed `$function` test.
/// @author Kitty Giraudel
/// @param {List} $list - List of items
/// @param {String} $function - Function to run on every item from `$list`
/// @param {Arglist} $args - Extra arguments to pass to `$function`
/// @return {Boolean}
/// @throw There is no `#{$function}` function.
@function every($list, $function, $args...) {
  @if not function-exists($function) {
    @error "There is no `#{$function}` function.";
  }
  
  @each $item in $list {
    @if not call($function, $item, $args...) {
      @return false;
    }
  }
  
  @return true;
}

用法

every {
  every: every(round ceil floor, function-exists);
  every: every(round ceil unknown, function-exists);
  every: every(completely unknown function, function-exists);
  
  every: every(4px 10px 20px, comparable, 42px);
  every: every(4px 10% 20px, comparable, 42%);
  every: every(4px 10px 20px, comparable, 42%);
}
every {
  every: true;
  every: false;
  every: false;
  every: true;
  every: false;
  every: false;
}

functions-walk()

functions-walk() 函数返回一个列表,该列表由每个函数调用的结果组成。

/// Return a list made of the result of each function call from `$functions` with `$args`.
/// @author Kitty Giraudel
/// @param {List} $functions - List of functions to call 
/// @param {Arglist} $args - Extra arguments to pass to each function in `$functions`
/// @return {List}
/// @throw There is no `#{$function}` function.
@function functions-walk($functions, $args...) {
  $list: ();
  
  @each $function in $functions {
    @if not function-exists($function) {
      @error "There is no `#{$function}` function.";
    }
    
    $list: append($list, call($function, $args...));
  }
  
  @return $list;
}

用法

functions-walk {
  functions-walk: functions-walk('red' 'blue' 'green', #BADA55);
  functions-walk: functions-walk('round' 'ceil' 'floor', 3.1415279);
}
functions-walk {
  functions-walk: 186 85 218;
  functions-walk: 3 4 3;
}