Stylus 函数

  • 返回值

    Stylus 具有强大的内置于语言层面的函数定义。函数定义与混入(mixins)一致,但是却可以返回值。
    一个很简单的例子:创建一个两数相加的函数。
    add(a, b)
      a + b
    
    我们可以将上述函数用在条件表达式中、作为属性值等等。
    body 
      padding add(10px, 5)
    
    输出为:
    body {
      padding: 15px;
    }
    
    Stylus 函数可以返回多个值,就像你给一个变量赋予多个值一样。
    例如,下面就是一个有效的赋值:
    sizes = 15px 10px
    sizes[0]
    // => 15px 
    
    类似的,我们可以在函数中返回多个值:
    sizes()
      15px 10px
    sizes()[0]
    // => 15px
    
    当返回值是标识符时是个小小的例外。例如,下面的代码对于 Stylus 来说看上去好像一个属性赋值(但是没有赋值操作符):
    swap(a, b)
      b a
    
    为避免歧义,我们可以使用括号,或是 return 关键字:
    swap(a, b)
      (b a)
    
    swap(a, b)
      return b a
    
  • 默认参数

    可选参数可以赋值一个表达式。在 Stylus 中,我们甚至可以使用参数列表中左侧的参数为右侧参数赋予默认值!
    例子:
    add(a, b)
    a + b add(a, b = a)
    a + b
    
    add(10, 5)
    // => 15
    
    add(10)
    // => 20
    
    注意:因为参数默认是赋值,因此我们可以使用函数调用作为默认值:
    add(a, b = unit(a, px))
      a + b
    
    函数可以接受命名参数。这可以免去记忆参数顺序的麻烦,或者说是提供了代码的可读性。
    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() 函数就可以起一个别名叫做 plus(),如下所示:
    plus = add
    plus(1, 2)
    // => 3
    
    函数可以接受命名参数。这可以免去记忆参数顺序的麻烦,或者说是提供了代码的可读性。
    subtract(a, b)
      a - b
    
    subtract(b: 10, a: 25)
    
    与为函数起 “别名” 一样,我们可以将函数作为参数传递。如下, invoke() 函数能够接收一个函数作为参数,因此我们可以将 add() 或 sub() 函数作为参数传递给 invoke()。
    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;
    }
    
    arguments 是所有函数体都能够访问的局部变量,包含了传递过来的所有参数。
    sum()
      n = 0
      for num in arguments
        n = n + num
    
    sum(1,2,3,4,5)
    // => 15
    
  • 条件

    假设我们想要创建一个名为 stringish() 的函数,用来决定参数是否可以转换为字符串。我们检查 val 是否是字符串或缩进(类似字符)。由于未定义的标识符将其自身作为值,因此我们就可以像下面一样对其自身进行比较(使用 yes 和 no 代替 true 和 false):
    add(a, b)
    a + b add(a, b = a)
    a + b
    
    add(10, 5)
    // => 15
    
    add(10)
    // => 20stringish(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
    
    注意: yes 和 no 并不是布尔字面量(boolean literals)。他们在这里只是简单的未定义标识符。
    subtract(a, b)
      a - b
    
    subtract(b: 10, a: 25)compare(a, b)
    if a > b
      higher
    else if a < b
      lower
    else
      equal
    
    用法:
    stringish('yay') == yes
    // => true
      
    stringish(yay) == yes
    // => true
      
    stringish(0) == no
    // => truecompare(5, 2)
    // => higher
    
    compare(1, 5)
    // => lower
    
    compare(10, 10)
    // => equal
    
  • 匿名函数

    利用 @(){} 语法可以在需要的地方使用匿名函数。下面展示了如何利用匿名函数创建一个自定义的 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
    
    下面我们定义了 get(hash, key) 函数,返回 key 的值或 null。我们遍历 hash 中的每个键值对(pair),如果键(key)相匹配则返回对应的值。
    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