運算子
運算子優先順序
以下是運算子優先順序表,由高到低
.
[]
! ~ + -
is defined
** * / %
+ -
... ..
<= >= < >
in
== is != is not isnt
is a
&& and || or
?:
= := ?= += -= *= /= %=
not
if unless
.
[]
! ~ + -
is defined
** * / %
+ -
... ..
<= >= < >
in
== is != is not isnt
is a
&& and || or
?:
= := ?= += -= *= /= %=
not
if unless
一元運算子
以下是一元運算子,!
、not
、-
、+
和 ~
。
!0
// => true
!!0
// => false
!1
// => false
!!5px
// => true
-5px
// => -5px
--5px
// => 5px
not true
// => false
not not true
// => true
!0
// => true
!!0
// => false
!1
// => false
!!5px
// => true
-5px
// => -5px
--5px
// => 5px
not true
// => false
not not true
// => true
邏輯 not
運算子的優先順序較低,因此以下範例可以用取代
a = 0
b = 1
!a and !b
// => false
// parsed as: (!a) and (!b)
a = 0
b = 1
!a and !b
// => false
// parsed as: (!a) and (!b)
使用
not a or b
// => false
// parsed as: not (a or b)
not a or b
// => false
// parsed as: not (a or b)
二元運算子
下標 []
下標運算子讓我們能透過索引(從 0 開始)取得表達式中的值。負索引值從表達式中的最後一個元素開始。
list = 1 2 3
list[0]
// => 1
list[-1]
// => 3
list = 1 2 3
list[0]
// => 1
list[-1]
// => 3
括號中的表達式可以作為元組(例如 (15px 5px)
、(1 2 3)
)。
以下是一個使用元組進行錯誤處理(並展示此結構的多功能性)的範例
add(a, b)
if a is a 'unit' and b is a 'unit'
a + b
else
(error 'a and b must be units!')
body
padding add(1,'5')
// => padding: error "a and b must be units";
padding add(1,'5')[0]
// => padding: error;
padding add(1,'5')[0] == error
// => padding: true;
padding add(1,'5')[1]
// => padding: "a and b must be units";
add(a, b)
if a is a 'unit' and b is a 'unit'
a + b
else
(error 'a and b must be units!')
body
padding add(1,'5')
// => padding: error "a and b must be units";
padding add(1,'5')[0]
// => padding: error;
padding add(1,'5')[0] == error
// => padding: true;
padding add(1,'5')[1]
// => padding: "a and b must be units";
以下是一個更複雜的範例。現在我們呼叫內建的 error()
函數,並傳回錯誤訊息,只要識別碼(第一個值)等於 error
。
if (val = add(1,'5'))[0] == error
error(val[1])
if (val = add(1,'5'))[0] == error
error(val[1])
範圍 .. ...
提供包含(..
)和排除(...
)範圍運算子,擴充至表達式
1..5
// => 1 2 3 4 5
1...5
// => 1 2 3 4
5..1
// => 5 4 3 2 1
1..5
// => 1 2 3 4 5
1...5
// => 1 2 3 4
5..1
// => 5 4 3 2 1
加法:+ -
乘法和加法二元運算子如預期般運作。類型轉換套用於單位類型類別中,或預設為文字值。例如 5s - 2px
的結果為 3s
。
15px - 5px
// => 10px
5 - 2
// => 3
5in - 50mm
// => 3.031in
5s - 1000ms
// => 4s
20mm + 4in
// => 121.6mm
"foo " + "bar"
// => "foo bar"
"num " + 15
// => "num 15"
15px - 5px
// => 10px
5 - 2
// => 3
5in - 50mm
// => 3.031in
5s - 1000ms
// => 4s
20mm + 4in
// => 121.6mm
"foo " + "bar"
// => "foo bar"
"num " + 15
// => "num 15"
乘法:/ * %
2000ms + (1s * 2)
// => 4000ms
5s / 2
// => 2.5s
4 % 2
// => 0
2000ms + (1s * 2)
// => 4000ms
5s / 2
// => 2.5s
4 % 2
// => 0
在屬性值中使用 /
時,必須用括號括起來。否則 /
會被視為文字(以支援 CSS line-height
)
font: 14px/1.5;
font: 14px/1.5;
但以下會評估為 14px
÷ 1.5
font: (14px/1.5);
font: (14px/1.5);
僅 /
運算子需要這樣做。
簡寫運算子:+= -= *= /= %=
簡寫運算子與其他常見語言類似。對於清單變數,第一個值會用來執行運算子,並覆寫清單以將其轉換為單值變數。對於字串,節點值只有 += 可作為附加函數。對於數字類型值,所有運算子都像一般數學運算一樣運作。顏色值也類似。
n = 12
n += 8
// => n = 20
int-list = 12 23 0 32
int-list %= 2
// => 12 % 2 = 0 (mod operator)
// => int-list = 0
mixed-list = node 23 'str'
mixed-list %= 2
// => error
mixed-list = node 23 'str' #2e7
mixed-list += 2
// => mixed-list = node2
s = 'str'
s += 2
// => s = 'str2'
c = #0e0
c -= #0e0
// => c = #000
n = 12
n += 8
// => n = 20
int-list = 12 23 0 32
int-list %= 2
// => 12 % 2 = 0 (mod operator)
// => int-list = 0
mixed-list = node 23 'str'
mixed-list %= 2
// => error
mixed-list = node 23 'str' #2e7
mixed-list += 2
// => mixed-list = node2
s = 'str'
s += 2
// => s = 'str2'
c = #0e0
c -= #0e0
// => c = #000
指數:**
指數運算子
2 ** 8
// => 256
2 ** 8
// => 256
相等性與關係:== != >= <= > <
相等性運算子可用於等同單位、顏色、字串,甚至識別碼。這是一個強大的概念,因為即使是任意識別碼(例如 wahoo
)也可以用作原子。函數可以傳回 yes
或 no
,而不是 true
或 false
(儘管不建議這樣做)。
5 == 5
// => true
10 > 5
// => true
#fff == #fff
// => true
true == false
// => false
wahoo == yay
// => false
wahoo == wahoo
// => true
"test" == "test"
// => true
true is true
// => true
'hey' is not 'bye'
// => true
'hey' isnt 'bye'
// => true
(foo bar) == (foo bar)
// => true
(1 2 3) == (1 2 3)
// => true
(1 2 3) == (1 1 3)
// => false
5 == 5
// => true
10 > 5
// => true
#fff == #fff
// => true
true == false
// => false
wahoo == yay
// => false
wahoo == wahoo
// => true
"test" == "test"
// => true
true is true
// => true
'hey' is not 'bye'
// => true
'hey' isnt 'bye'
// => true
(foo bar) == (foo bar)
// => true
(1 2 3) == (1 2 3)
// => true
(1 2 3) == (1 1 3)
// => false
只有精確值相符。例如,0 == false
和 null == false
都是 false
。
別名
== is
!= is not
!= isnt
== is
!= is not
!= isnt
真值
Stylus 中幾乎所有內容都解析為 true
,包括帶有後綴的單位。即使是 0%
、0px
等也會解析為 true
(因為在 Stylus 中,混入或函數通常會接受單位作為有效值)。
但是,就算術而言,0
本身是 false
。
長度大於 1 的表達式(或「清單」)被視為真值。
true
範例
0%
0px
1px
-1
-1px
hey
'hey'
(0 0 0)
('' '')
0%
0px
1px
-1
-1px
hey
'hey'
(0 0 0)
('' '')
false
範例
0
null
false
''
0
null
false
''
邏輯運算子:&& || and or
邏輯運算子 &&
和 ||
是別名 and
/ or
,它們套用相同的優先順序。
5 && 3
// => 3
0 || 5
// => 5
0 && 5
// => 0
#fff is a 'rgba' and 15 is a 'unit'
// => true
5 && 3
// => 3
0 || 5
// => 5
0 && 5
// => 0
#fff is a 'rgba' and 15 is a 'unit'
// => true
存在運算子:in
檢查 左邊 運算元在 右邊 表達式中是否存在。
簡單範例
nums = 1 2 3
1 in nums
// => true
5 in nums
// => false
nums = 1 2 3
1 in nums
// => true
5 in nums
// => false
一些未定義的識別碼
words = foo bar baz
bar in words
// => true
HEY in words
// => false
words = foo bar baz
bar in words
// => true
HEY in words
// => false
也可以用於元組
vals = (error 'one') (error 'two')
error in vals
// => false
(error 'one') in vals
// => true
(error 'two') in vals
// => true
(error 'something') in vals
// => false
vals = (error 'one') (error 'two')
error in vals
// => false
(error 'one') in vals
// => true
(error 'two') in vals
// => true
(error 'something') in vals
// => false
混入中的範例用法
pad(types = padding, n = 5px)
if padding in types
padding n
if margin in types
margin n
body
pad()
body
pad(margin)
body
pad(padding margin, 10px)
pad(types = padding, n = 5px)
if padding in types
padding n
if margin in types
margin n
body
pad()
body
pad(margin)
body
pad(padding margin, 10px)
產生
body {
padding: 5px;
}
body {
margin: 5px;
}
body {
padding: 10px;
margin: 10px;
}
body {
padding: 5px;
}
body {
margin: 5px;
}
body {
padding: 10px;
margin: 10px;
}
條件賦值:?= :=
條件賦值運算子 ?=
(別名為 :=
)讓我們可以在不覆蓋舊值(如果存在)的情況下定義變數。此運算子會擴充為三元運算中的 is defined
二元運算。
例如,下列範例是等效的
color := white
color ?= white
color = color is defined ? color : white
color := white
color ?= white
color = color is defined ? color : white
使用一般的 =
時,我們只是重新指派
color = white
color = black
color
// => black
color = white
color = black
color
// => black
但使用 ?=
時,我們的第二次嘗試會失敗(因為變數已經定義)
color = white
color ?= black
color
// => white
color = white
color ?= black
color
// => white
實例檢查:是一個
Stylus 提供一個名為 is a
的二元運算子,用於類型檢查。
15 is a 'unit'
// => true
#fff is a 'rgba'
// => true
15 is a 'rgba'
// => false
15 is a 'unit'
// => true
#fff is a 'rgba'
// => true
15 is a 'rgba'
// => false
或者,我們可以使用 type()
BIF
type(#fff) == 'rgba'
// => true
type(#fff) == 'rgba'
// => true
注意: color
是唯一的特殊情況,當左手運算元是 RGBA
或 HSLA
節點時,會評估為 true
。
變數定義:已定義
這個偽二元運算子不接受右手運算元,並且不會評估左手。這讓我們可以檢查變數是否有指派值。
foo is defined
// => false
foo = 15px
foo is defined
// => true
#fff is defined
// => 'invalid "is defined" check on non-variable #fff'
foo is defined
// => false
foo = 15px
foo is defined
// => true
#fff is defined
// => 'invalid "is defined" check on non-variable #fff'
或者,可以使用 lookup(name)
內建函數來執行此操作,或執行動態查詢
name = 'blue'
lookup('light-' + name)
// => null
light-blue = #80e2e9
lookup('light-' + name)
// => #80e2e9
name = 'blue'
lookup('light-' + name)
// => null
light-blue = #80e2e9
lookup('light-' + name)
// => #80e2e9
這個運算子是必要的,因為未定義的識別碼仍然是真值。例如
body
if ohnoes
padding 5px
body
if ohnoes
padding 5px
未定義時會產生下列 CSS
body {
padding: 5px;
}
body {
padding: 5px;
}
然而這會是安全的
body
if ohnoes is defined
padding 5px
body
if ohnoes is defined
padding 5px
三元
三元運算子在大部分語言中都像我們預期的那樣運作。它是唯一具有三個運算元的運算子(條件表達式、真表達式和假表達式)。
num = 15
num ? unit(num, 'px') : 20px
// => 15px
num = 15
num ? unit(num, 'px') : 20px
// => 15px
強制轉型
作為 unit()
內建函數的簡潔替代方案,語法 (expr) unit
可用於強制後綴。
body
n = 5
foo: (n)em
foo: (n)%
foo: (n + 5)%
foo: (n * 5)px
foo: unit(n + 5, '%')
foo: unit(5 + 180 / 2, deg)
body
n = 5
foo: (n)em
foo: (n)%
foo: (n + 5)%
foo: (n * 5)px
foo: unit(n + 5, '%')
foo: unit(5 + 180 / 2, deg)
顏色運算
對顏色的操作提供簡潔、有表現力的方式來改變組成。例如,我們可以對每個 RGB
#0e0 + #0e0
// => #0f0
#0e0 + #0e0
// => #0f0
另一個範例是透過加或減百分比來調整明度值。要使顏色變亮,請加;要使顏色變暗,請減。
#888 + 50%
// => #c3c3c3
#888 - 50%
// => #444
#888 + 50%
// => #c3c3c3
#888 - 50%
// => #444
也可以透過加或減度數來調整色相。例如,將 50deg
加到這個紅色值會產生一個黃色
#f00 + 50deg
// => #ffd500
#f00 + 50deg
// => #ffd500
值會適當地固定。例如,我們可以將色相「旋轉」180度,如果目前的值是 320deg
,它將解析為 140deg
。
我們也可以一次調整多個值(包括 alpha),方法是使用 rgb()
、rgba()
、hsl()
或 hsla()
#f00 - rgba(100,0,0,0.5)
// => rgba(155,0,0,0.5)
#f00 - rgba(100,0,0,0.5)
// => rgba(155,0,0,0.5)
Sprintf
字串 sprintf 類型的運算子 %
可用於產生一個字面值,在內部透過 s()
內建函式傳遞參數
'X::Microsoft::Crap(%s)' % #fc0
// => X::Microsoft::Crap(#fc0)
'X::Microsoft::Crap(%s)' % #fc0
// => X::Microsoft::Crap(#fc0)
多個值應加上括號
'-webkit-gradient(%s, %s, %s)' % (linear (0 0) (0 100%))
// => -webkit-gradient(linear, 0 0, 0 100%)
'-webkit-gradient(%s, %s, %s)' % (linear (0 0) (0 100%))
// => -webkit-gradient(linear, 0 0, 0 100%)