跳至内容

函数

Stylus 具有强大的语言内函数定义功能。函数定义看起来与 mixin 相同;但是,函数可以返回值。

返回值

我们尝试一个简单的示例:创建一个添加两个数字的函数。

add(a, b)
  a + b
add(a, b)
  a + b

然后,我们可以在条件、属性值等中使用此函数。

body 
  padding add(10px, 5)
body 
  padding add(10px, 5)

渲染

body {
  padding: 15px;
}
body {
  padding: 15px;
}

参数默认值

可选参数可以默认为给定表达式。使用 Stylus,我们甚至可以将参数默认为前面的参数!

例如

add(a, b = a)
  a + b

add(10, 5)
// => 15

add(10)
// => 20
add(a, b = a)
  a + b

add(10, 5)
// => 15

add(10)
// => 20

注意:由于参数默认值是赋值,因此我们也可以将函数调用用于默认值

add(a, b = unit(a, px))
  a + b
add(a, b = unit(a, px))
  a + b

命名参数

函数接受命名参数。这使你无需记住参数的顺序,或者只是提高代码的可读性。

例如

subtract(a, b)
  a - b

subtract(b: 10, a: 25)
subtract(a, b)
  a - b

subtract(b: 10, a: 25)

函数体

我们可以进一步使用我们的简单 add() 函数。我们通过 unit() 内置函数将作为 px 传递的所有单位强制转换。它重新分配每个参数,并提供单位类型字符串(或标识符),忽略单位转换。

add(a, b = a)
  a = unit(a, px)
  b = unit(b, px)
  a + b

add(15%, 10deg)
// => 25
add(a, b = a)
  a = unit(a, px)
  b = unit(b, px)
  a + b

add(15%, 10deg)
// => 25

多个返回值

Stylus 函数可以返回多个值,就像你可以将多个值分配给变量一样。

例如,以下是一个有效的赋值

sizes = 15px 10px

sizes[0]
// => 15px 
sizes = 15px 10px

sizes[0]
// => 15px 

同样,我们可以返回多个值

sizes()
  15px 10px

sizes()[0]
// => 15px
sizes()
  15px 10px

sizes()[0]
// => 15px

一个轻微的例外是当返回值是标识符时。例如,以下看起来像 Stylus 的属性赋值(因为没有运算符)

swap(a, b)
  b a
swap(a, b)
  b a

为了消除歧义,我们可以用括号括起来,或使用 return 关键字

swap(a, b)
  (b a)

swap(a, b)
  return b a
swap(a, b)
  (b a)

swap(a, b)
  return b a

条件

假设我们想要创建一个名为 stringish() 的函数来确定参数是否可以转换为字符串。我们检查 val 是否为字符串或标识符(类似于字符串)。因为未定义的标识符会将自身作为值返回,所以我们可以将它们与自身进行比较,如下所示(其中 yesno 用于代替 truefalse

stringish(val)
  if val is a 'string' or val is a 'ident'
    yes
  else
    no
stringish(val)
  if val is a 'string' or val is a 'ident'
    yes
  else
    no

用法

stringish('yay') == yes
// => true

stringish(yay) == yes
// => true

stringish(0) == no
// => true
stringish('yay') == yes
// => true

stringish(yay) == yes
// => true

stringish(0) == no
// => true

注意yesno 不是布尔文字。在这种情况下,它们只是未定义的标识符。

另一个示例

compare(a, b)
  if a > b
    higher
  else if a < b
    lower
  else
    equal
compare(a, b)
  if a > b
    higher
  else if a < b
    lower
  else
    equal

用法

compare(5, 2)
// => higher

compare(1, 5)
// => lower

compare(10, 10)
// => equal
compare(5, 2)
// => higher

compare(1, 5)
// => lower

compare(10, 10)
// => equal

别名

要给函数起别名,只需将函数名称分配给一个新标识符。例如,我们的 add() 函数可以像这样别名为 plus()

plus = add

plus(1, 2)
// => 3
plus = add

plus(1, 2)
// => 3

变量函数

就像我们可以给函数“起别名”一样,我们也可以传递一个函数。这里,我们的 invoke() 函数接受一个函数,因此我们可以将 add()sub() 传递给它。

add(a, b)
  a + b

sub(a, b)
  a - b

invoke(a, b, fn)
  fn(a, b)

body
  padding invoke(5, 10, add)
  padding invoke(5, 10, sub)
add(a, b)
  a + b

sub(a, b)
  a - b

invoke(a, b, fn)
  fn(a, b)

body
  padding invoke(5, 10, add)
  padding invoke(5, 10, sub)

生成

body {
  padding: 15;
  padding: -5;
}
body {
  padding: 15;
  padding: -5;
}

匿名函数

您可以在需要时使用 @(){} 语法使用匿名函数。以下是如何使用它创建自定义 sort() 函数

sort(list, fn = null)
  // default sort function
  if fn == null
    fn = @(a, b) {
      a > b
    }

  // bubble sort
  for $i in 1..length(list) - 1
    for $j in 0..$i - 1
      if fn(list[$j], list[$i])
        $temp = list[$i]
        list[$i] = list[$j]
        list[$j] = $temp
  return list

  sort('e' 'c' 'f' 'a' 'b' 'd')
  // => 'a' 'b' 'c' 'd' 'e' 'f'

  sort(5 3 6 1 2 4, @(a, b){
    a < b
  })
  // => 6 5 4 3 2 1
sort(list, fn = null)
  // default sort function
  if fn == null
    fn = @(a, b) {
      a > b
    }

  // bubble sort
  for $i in 1..length(list) - 1
    for $j in 0..$i - 1
      if fn(list[$j], list[$i])
        $temp = list[$i]
        list[$i] = list[$j]
        list[$j] = $temp
  return list

  sort('e' 'c' 'f' 'a' 'b' 'd')
  // => 'a' 'b' 'c' 'd' 'e' 'f'

  sort(5 3 6 1 2 4, @(a, b){
    a < b
  })
  // => 6 5 4 3 2 1

参数

arguments 局部变量可用于所有函数体,并包含传递的所有参数。

例如

sum()
  n = 0
  for num in arguments
    n = n + num

sum(1,2,3,4,5)
// => 15
sum()
  n = 0
  for num in arguments
    n = n + num

sum(1,2,3,4,5)
// => 15

哈希示例

下面我们定义 get(hash, key) 函数,它返回 key 的值(或 null)。我们遍历 hash 中的每个 pair,当第一个(key)匹配时返回 pair 的第二个节点。

get(hash, key)
  return pair[1] if pair[0] == key for pair in hash
get(hash, key)
  return pair[1] if pair[0] == key for pair in hash

如下所示,语言内函数(与强大的 Stylus 表达式配对)可以提供极大的灵活性

hash = (one 1) (two 2) (three 3)

get(hash, two)
// => 2

get(hash, three)
// => 3

get(hash, something)
// => null
hash = (one 1) (two 2) (three 3)

get(hash, two)
// => 2

get(hash, three)
// => 3

get(hash, something)
// => null