コンテンツへスキップ
トップへ戻る

演算子

演算子の優先順位

以下は、優先順位の高い順に並べた演算子の優先順位表です。

.
[]
! ~ + -
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 - 2px3sになります。

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などの任意の識別子をアトムとして使用できます。(推奨されませんが)関数ではtrueまたはfalseの代わりにyesまたはnoを返すことができます。

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 == falsenull == 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

しかし、?=を使用する場合、2回目の試行は失敗します(変数が既に定義されているため)。

color = white
color ?= black

color
// => white
color = white
color ?= black

color
// => white

インスタンスチェック: is a

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になります。

変数の定義: is defined

この擬似二項演算子は右辺の演算子を受け入れず、左辺も評価しません。これにより、変数に値が割り当てられているかどうかを確認できます。

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

三項演算子

三項演算子は、ほとんどの言語で期待どおりに動作します。これは、3つのオペランド(条件式、式、および式)を持つ唯一の演算子です。

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になります。

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%)