跳到內容

函數

Stylus 具有強大的內建函數定義功能。函數定義看起來與混入相同;但是,函數可以傳回一個值。

傳回值

讓我們嘗試一個簡單的範例:建立一個可以相加兩個數字的函數。

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