Scala 3 โ€” Book

Scala for JavaScript Developers

Language

ๆญค้กต้ขๆไพ›ไบ† JavaScript ๅ’Œ Scala ็ผ–็จ‹่ฏญ่จ€ไน‹้—ด็š„ๆฏ”่พƒใ€‚ ๅฎƒ้€‚็”จไบŽไบ†่งฃ JavaScript ๅนถๅธŒๆœ›ไบ†่งฃ Scala ็š„็จ‹ๅบๅ‘˜๏ผŒ็‰นๅˆซๆ˜ฏ้€š่ฟ‡ๆŸฅ็œ‹ JavaScript ่ฏญ่จ€ๅŠŸ่ƒฝไธŽ Scala ๆฏ”่พƒ็š„็คบไพ‹ใ€‚

ๆฆ‚่ฟฐ

ๆœฌ่Š‚ๅฏนไปฅไธ‹ๅ„่Š‚่ฟ›่กŒไบ†็›ธๅฏน็ฎ€็Ÿญ็š„ไป‹็ปๅ’Œๆ€ป็ป“ใ€‚ ๅฎƒไปŽ้ซ˜ๅฑ‚ๆฌกไธŠไป‹็ปไบ† JavaScript ๅ’Œ Scala ไน‹้—ด็š„ๅผ‚ๅŒ๏ผŒ็„ถๅŽไป‹็ปไบ†ๆ‚จๅœจๆฏๅคฉ็ผ–ๅ†™ไปฃ็ ๆ—ถไผš้‡ๅˆฐ็š„ๅทฎๅผ‚ใ€‚

้ซ˜ๅฑ‚ๆฌก็š„็›ธไผผๆ€ง

ๅœจ้ซ˜ๅฑ‚ๆฌกไธŠ๏ผŒScala ไธŽ JavaScript ๆœ‰ไปฅไธ‹็›ธไผผไน‹ๅค„๏ผš

  • ไธค่€…้ƒฝ่ขซ่ฎคไธบๆ˜ฏ้ซ˜็บง็ผ–็จ‹่ฏญ่จ€๏ผŒๆ‚จไธๅฟ…ๅ…ณๅฟƒๆŒ‡้’ˆๅ’Œๆ‰‹ๅŠจๅ†…ๅญ˜็ฎก็†็ญ‰ไฝŽ็บงๆฆ‚ๅฟต
  • ไธค่€…้ƒฝๆœ‰ไธ€ไธช็›ธๅฏน็ฎ€ๅ•ใ€็ฎ€ๆด็š„่ฏญๆณ•
  • ไธค่€…้ƒฝๆ”ฏๆŒ C/C++/Java ้ฃŽๆ ผ็š„่Šฑๆ‹ฌๅท่ฏญๆณ•๏ผŒ็”จไบŽ็ผ–ๅ†™ๆ–นๆณ•ๅ’Œๅ…ถไป–ไปฃ็ ๅ—
  • ไธค่€…้ƒฝๅŒ…ๆ‹ฌ้ขๅ‘ๅฏน่ฑก็ผ–็จ‹ (OOP) ็š„็‰นๆ€ง๏ผˆๅฆ‚็ฑป๏ผ‰
  • ไธค่€…้ƒฝๅŒ…ๅซ็”จไบŽ ๅ‡ฝๆ•ฐๅผ็ผ–็จ‹ (FP) ็š„๏ผˆๅฆ‚ lambda๏ผ‰
  • JavaScript ๅœจๆต่งˆๅ™จๅ’Œ Node.js ็ญ‰ๅ…ถไป–็Žฏๅขƒไธญ่ฟ่กŒใ€‚ Scala ็š„ Scala.js ้ฃŽๆ ผไปฅ JavaScript ไธบ็›ฎๆ ‡๏ผŒๅ› ๆญค Scala ็จ‹ๅบๅฏไปฅๅœจ็›ธๅŒ็š„็Žฏๅขƒไธญ่ฟ่กŒใ€‚
  • ๅผ€ๅ‘ไบบๅ‘˜ไฝฟ็”จ Node.js ๅœจ JavaScript ๅ’Œ Scala ไธญ็ผ–ๅ†™ๆœๅŠกๅ™จ็ซฏๅบ”็”จ็จ‹ๅบ๏ผ› Play Framework ไน‹็ฑป็š„้กน็›ฎไนŸๅฏไปฅ่ฎฉๆ‚จๅœจ Scala ไธญ็ผ–ๅ†™ๆœๅŠกๅ™จ็ซฏๅบ”็”จ็จ‹ๅบ
  • ไธค็ง่ฏญ่จ€้ƒฝๆœ‰็›ธไผผ็š„ if ่ฏญๅฅใ€while ๅพช็Žฏๅ’Œ for ๅพช็Žฏ
  • ไปŽ ๅœจ่ฟ™ไธช Scala.js ้กต้ข ๅผ€ๅง‹๏ผŒๆ‚จไผšๅ‘็Žฐ่ฎธๅคšๆ”ฏๆŒ Reactใ€Angularใ€jQuery ๅ’Œ่ฎธๅคšๅ…ถไป– JavaScript ๅ’ŒScala ๅบ“
  • JavaScript ๅฏน่ฑกๆ˜ฏๅฏๅ˜็š„๏ผ›ไปฅๅ‘ฝไปคๅผ้ฃŽๆ ผ็ผ–ๅ†™ๆ—ถ๏ผŒScala ๅฏน่ฑก_ๅฏไปฅ_ๆ˜ฏๅฏๅ˜็š„
  • JavaScript ๅ’Œ Scala ้ƒฝๆ”ฏๆŒ promises ไฝœไธบๅค„็†ๅผ‚ๆญฅ่ฎก็ฎ—็ป“ๆžœ็š„ไธ€็งๆ–นๅผ๏ผˆScala concurrency ไฝฟ็”จๆœŸ่ดงๅ’Œๆ‰ฟ่ฏบ๏ผ‰

้ซ˜ๅฑ‚ๆฌกๅทฎๅผ‚

ๅŒๆ ทๅœจ้ซ˜ๅฑ‚ๆฌกไธŠ๏ผŒJavaScript ๅ’Œ Scala ไน‹้—ด็š„ไธ€ไบ›ๅŒบๅˆซๆ˜ฏ๏ผš

  • JavaScript ๆ˜ฏๅŠจๆ€็ฑปๅž‹็š„๏ผŒScala ๆ˜ฏ้™ๆ€็ฑปๅž‹็š„
    • ๅฐฝ็ฎก Scala ๆ˜ฏ้™ๆ€็ฑปๅž‹็š„๏ผŒไฝ†็ฑปๅž‹ๆŽจๆ–ญไน‹็ฑป็š„็‰นๆ€ง่ฎฉๅฎƒๆ„Ÿ่ง‰ๅƒๆ˜ฏไธ€็งๅŠจๆ€่ฏญ่จ€๏ผˆๆญฃๅฆ‚ๆ‚จๅฐ†ๅœจไธ‹้ข็š„็คบไพ‹ไธญ็œ‹ๅˆฐ็š„้‚ฃๆ ท๏ผ‰
  • Scala ๆƒฏ็”จ่ฏญ้ป˜่ฎคๆ”ฏๆŒไธๅ˜ๆ€ง๏ผš้ผ“ๅŠฑๆ‚จไฝฟ็”จไธๅฏๅ˜ๅ˜้‡ๅ’Œไธๅฏๅ˜้›†ๅˆ
  • Scala ่ฏญๆณ•็ฎ€ๆดๆ˜“่ฏป๏ผ›ๆˆ‘ไปฌ็งฐไน‹ไธบ_่กจ็ŽฐๅŠ›_
  • Scala ๆ˜ฏไธ€็ง็บฏ OOP ่ฏญ่จ€๏ผŒๅ› ๆญคๆฏไธชๅฏน่ฑก้ƒฝๆ˜ฏ็ฑป็š„ไธ€ไธชๅฎžไพ‹๏ผŒ่€Œๅƒ่ฟ็ฎ—็ฌฆไธ€ๆ ท็š„็ฌฆๅท + ๅ’Œ += ๆ˜ฏ็œŸๆญฃ็š„ๆ–นๆณ•๏ผ›่ฟ™ๆ„ๅ‘ณ็€ๆ‚จๅฏไปฅๅˆ›ๅปบ่‡ชๅทฑ็š„ๆ–นๆณ•ไฝœไธบ่ฟ็ฎ—็ฌฆ
  • ไฝœไธบไธ€็ง็บฏ OOP ่ฏญ่จ€ๅ’Œ็บฏ FP ่ฏญ่จ€๏ผŒScala ้ผ“ๅŠฑ OOP ๅ’Œ FP ็š„่žๅˆ๏ผŒๅ…ทๆœ‰็”จไบŽ้€ป่พ‘็š„ๅ‡ฝๆ•ฐๅ’Œ็”จไบŽๆจกๅ—ๅŒ–็š„ไธๅฏๅ˜ๅฏน่ฑก
  • Scala ๆ‹ฅๆœ‰ๆœ€ๅ…ˆ่ฟ›็š„็ฌฌไธ‰ๆ–นๅผ€ๆบๅ‡ฝๆ•ฐๅผ็ผ–็จ‹ๅบ“
  • Scala ไธญ็š„ไธ€ๅˆ‡้ƒฝๆ˜ฏไธ€ไธช_่กจ่พพๅผ_๏ผšๅƒ if ่ฏญๅฅใ€for ๅพช็Žฏใ€match ่กจ่พพๅผ๏ผŒ็”š่‡ณ try/catch ่กจ่พพๅผ้ƒฝๆœ‰่ฟ”ๅ›žๅ€ผ
  • Scala Native ้กน็›ฎ่ฎฉๆ‚จๅฏไปฅ็ผ–ๅ†™โ€œ็ณป็ปŸโ€็บงไปฃ็ ๏ผŒไนŸๅฏไปฅ็ผ–่ฏ‘ไธบๆœฌๆœบๅฏๆ‰ง่กŒๆ–‡ไปถ

็ผ–็จ‹ๅฑ‚ๆฌกๅทฎๅผ‚

ๅœจ่พƒไฝŽ็š„ๅฑ‚ๆฌกไธŠ๏ผŒ่ฟ™ไบ›ๆ˜ฏๆ‚จๅœจ็ผ–ๅ†™ไปฃ็ ๆ—ถๆฏๅคฉ้ƒฝไผš็œ‹ๅˆฐ็š„ไธ€ไบ›ๅทฎๅผ‚๏ผš

  • Scala ๅ˜้‡ๅ’Œๅ‚ๆ•ฐไฝฟ็”จ val๏ผˆไธๅฏๅ˜๏ผŒๅฆ‚ JavaScript const๏ผ‰ๆˆ– var๏ผˆๅฏๅ˜๏ผŒๅฆ‚ JavaScript var ๆˆ– let๏ผ‰ๅฎšไน‰
  • Scala ไธๅœจ่กŒๅฐพไฝฟ็”จๅˆ†ๅท
  • Scala ๆ˜ฏ้™ๆ€็ฑปๅž‹็š„๏ผŒๅฐฝ็ฎกๅœจ่ฎธๅคšๆƒ…ๅ†ตไธ‹ๆ‚จไธ้œ€่ฆๅฃฐๆ˜Ž็ฑปๅž‹
  • Scala ไฝฟ็”จ trait ไฝœไธบๆŽฅๅฃๅนถๅˆ›ๅปบ_ๆททๆญ_
  • ้™คไบ†็ฎ€ๅ•็š„ for ๅพช็Žฏไน‹ๅค–๏ผŒScala ่ฟ˜ๅ…ทๆœ‰ๅผบๅคง็š„ for comprehensions๏ผŒๅฏไปฅๆ นๆฎๆ‚จ็š„็ฎ—ๆณ•ไบง็”Ÿ็ป“ๆžœ
  • ๆจกๅผๅŒน้…ๅ’Œ match ่กจ่พพๅผๅฐ†ๆ”นๅ˜ไฝ ็ผ–ๅ†™ไปฃ็ ็š„ๆ–นๅผ
  • Scala ็š„ Scala ็š„ ไธŠไธ‹ๆ–‡ๆŠฝ่ฑก ๅ’Œ ๆœฏ่ฏญๆŽจๅฏผ ๆไพ›ไบ†ไธ€็ณปๅˆ—็‰นๆ€ง๏ผš
    • ๆ‰ฉๅฑ•ๆ–นๆณ• ๅ…่ฎธๆ‚จๅœจไธ็ ดๅๆจกๅ—ๅŒ–็š„ๆƒ…ๅ†ตไธ‹ๅ‘ๅฐ้—ญ็ฑปๆทปๅŠ ๆ–ฐๅŠŸ่ƒฝ๏ผŒๆ–นๆณ•ๆ˜ฏไป…ๅœจ็‰นๅฎš่Œƒๅ›ดๅ†…ๅฏ็”จ๏ผˆไธŽ็Œดๅญ่กฅไธ็›ธๅ๏ผŒๅฎƒไผšๆฑกๆŸ“ไปฃ็ ็š„ๅ…ถไป–ๅŒบๅŸŸ๏ผ‰
    • ็ป™ๅฎžไพ‹ ่ฎฉๆ‚จๅฎšไน‰็ผ–่ฏ‘ๅ™จๅฏไปฅ็”จๆฅไธบๆ‚จๅˆๆˆไปฃ็ ็š„ๆœฏ่ฏญ
    • ็ฑปๅž‹ๅฎ‰ๅ…จๅ’Œๅคšๅ…ƒ็ญ‰ๅผ่ฎฉๆ‚จๅฐ†็›ธ็ญ‰ๆฏ”่พƒโ€”โ€”ๅœจ็ผ–่ฏ‘ๆ—ถโ€”โ€”ไป…้™ไบŽ้‚ฃไบ›ๆœ‰ๆ„ไน‰็š„ๆฏ”่พƒ
  • ็”ฑไบŽๅ็งฐๅ‚ๆ•ฐใ€ไธญ็ผ€็ฌฆๅทใ€ๅฏ้€‰ๆ‹ฌๅทใ€ๆ‰ฉๅฑ•ๆ–นๆณ•ๅ’Œ ้ซ˜้˜ถๅ‡ฝๆ•ฐ ็ญ‰ๅŠŸ่ƒฝ๏ผŒๆ‚จๅฏไปฅๅˆ›ๅปบ่‡ชๅทฑ็š„โ€œๆŽงๅˆถ็ป“ๆž„โ€ๅ’Œ DSL
  • ๆ‚จๅฏไปฅๅœจๆœฌไนฆไธญ้˜…่ฏปๅˆฐ่ฎธๅคšๅ…ถไป–ๅฅฝไธœ่ฅฟ๏ผšๆ ทไพ‹็ฑปใ€ไผด็”Ÿ็ฑปๅ’Œๅฏน่ฑกใ€ๅฎใ€[่”ๅˆ][union-type]ๅ’Œไบค้›†็ฑปๅž‹ใ€ๅคšๅ‚ๆ•ฐๅˆ—่กจใ€ๅ‘ฝๅๅ‚ๆ•ฐ็ญ‰

ๅ˜้‡ๅ’Œ็ฑปๅž‹

ๆณจ้‡Š

//
/* ... */
/** ... */
//
/* ... */
/** ... */

ๅฏๅ˜ๅ˜้‡

let   // now preferred for mutable
var   // old mutable style
var  // used for mutable variables

ไธๅฏๅ˜ๅ˜้‡

const
val

Scala ็š„็ป้ชŒๆณ•ๅˆ™ๆ˜ฏไฝฟ็”จ val ๅฃฐๆ˜Žๅ˜้‡๏ผŒ้™ค้žๆœ‰็‰นๅฎšๅŽŸๅ› ้œ€่ฆๅฏๅ˜ๅ˜้‡ใ€‚

ๅ‘ฝๅๆ ‡ๅ‡†

JavaScript ๅ’Œ Scala ้€šๅธธไฝฟ็”จ็›ธๅŒ็š„ CamelCase ๅ‘ฝๅๆ ‡ๅ‡†ใ€‚ ๅ˜้‡ๅ‘ฝๅไธบ myVariableName๏ผŒๆ–นๆณ•ๅ‘ฝๅไธบ lastIndexOf๏ผŒ็ฑปๅ’Œๅฏน่ฑกๅ‘ฝๅไธบ Animal ๅ’Œ PrintedBook ใ€‚

ๅญ—็ฌฆไธฒ

JavaScript ๅ’Œ Scala ไธญๅญ—็ฌฆไธฒ็š„่ฎธๅคš็”จๆณ•็›ธไผผ๏ผŒไฝ† Scala ไป…ๅฏน็ฎ€ๅ•ๅญ—็ฌฆไธฒไฝฟ็”จๅŒๅผ•ๅท๏ผŒๅฏนๅคš่กŒๅญ—็ฌฆไธฒไฝฟ็”จไธ‰ๅผ•ๅทใ€‚

ๅญ—็ฌฆไธฒๅŸบ็ก€

// use single- or double-quotes
let msg = 'Hello, world';
let msg = "Hello, world";
// use only double-quotes
val msg = "Hello, world"

ๆ’ๅ…ฅ

let name = 'Joe';

// JavaScript uses backticks
let msg = `Hello, ${name}`;
val name = "Joe"
val age = 42
val weight = 180.5

// use `s` before a string for simple interpolation
println(s"Hi, $name")   // "Hi, Joe"
println(s"${1 + 1}")    // "2"

// `f` before a string allows printf-style formatting.
// this example prints:
// "Joe is 42 years old, and weighs"
// "180.5 pounds."
println(f"$name is $age years old, and weighs $weight%.1f pounds.")

ๅธฆๆ’ๅ…ฅ็š„ๅคš่กŒๅญ—็ฌฆไธฒ

let name = "joe";
let str = `
Hello, ${name}.
This is a multiline string.
`;
val name = "Martin Odersky"

val quote = s"""
|$name says
|Scala is a fusion of
|OOP and FP.
""".stripMargin.replaceAll("\n", " ").trim

// result:
// "Martin Odersky says Scala is a fusion of OOP and FP."

JavaScript ๅ’Œ Scala ไนŸๆœ‰็ฑปไผผ็š„ๅค„็†ๅญ—็ฌฆไธฒ็š„ๆ–นๆณ•๏ผŒๅŒ…ๆ‹ฌ charAtใ€concatใ€indexOf ็ญ‰็ญ‰ใ€‚ \nใ€\fใ€\t ็ญ‰่ฝฌไน‰ๅญ—็ฌฆๅœจไธค็ง่ฏญ่จ€ไธญไนŸๆ˜ฏ็›ธๅŒ็š„ใ€‚

ๆ•ฐๅญ—ๅ’Œ็ฎ—ๆœฏ

JavaScript ๅ’Œ Scala ไน‹้—ด็š„ๆ•ฐๅญ—่ฟ็ฎ—็ฌฆๅพˆ็›ธไผผใ€‚ ๆœ€ๅคง็š„ไธๅŒๆ˜ฏ Scala ไธๆไพ› ++ ๅ’Œ -- ่ฟ็ฎ—็ฌฆใ€‚

ๆ•ฐๅญ—่ฟ็ฎ—็ฌฆ๏ผš

let x = 1;
let y = 2.0;
 
let a = 1 + 1;
let b = 2 - 1;
let c = 2 * 2;
let d = 4 / 2;
let e = 5 % 2;
val x = 1
val y = 2.0
 
val a = 1 + 1
val b = 2 - 1
val c = 2 * 2
val d = 4 / 2
val e = 5 % 2

่‡ชๅขžๅ’Œ่‡ชๅ‡๏ผš

i++;
i += 1;

i--;
i -= 1;
i += 1;
i -= 1;

ๆˆ–่ฎธๆœ€ๅคง็š„ๅŒบๅˆซๅœจไบŽๅƒ+ๅ’Œ-่ฟ™ๆ ท็š„โ€œๆ“ไฝœ็ฌฆโ€ๅœจScalaไธญๅฎž้™…ไธŠๆ˜ฏ_ๆ–นๆณ•_๏ผŒ่€Œไธๆ˜ฏๆ“ไฝœ็ฌฆใ€‚ Scala ๆ•ฐๅญ—ไนŸๆœ‰่ฟ™ไบ›็›ธๅ…ณ็š„ๆ–นๆณ•๏ผš

var a = 2
a *= 2      // 4
a /= 2      // 2

Scala ็š„ Double ็ฑปๅž‹ๆœ€ๆŽฅ่ฟ‘ไบŽ JavaScript ็š„้ป˜่ฎค number ็ฑปๅž‹๏ผŒ Int ่กจ็คบๆœ‰็ฌฆๅท็š„ 32 ไฝๆ•ดๆ•ฐๅ€ผ๏ผŒ่€Œ BigInt ๅฏนๅบ”ไบŽ JavaScript ็š„ bigintใ€‚

่ฟ™ไบ›ๆ˜ฏ Scala Int ๅ’Œ Double ๅ€ผใ€‚ ่ฏทๆณจๆ„๏ผŒ็ฑปๅž‹ไธๅฟ…ๆ˜พๅผๅฃฐๆ˜Ž๏ผš

val i = 1     // Int
val d = 1.1   // Double

ไฝ ๅฏไปฅๆŒ‰้œ€่ฆไฝฟ็”จๅ…ถๅฎƒๆ•ฐๅญ—็ฑปๅž‹๏ผš

val a: Byte = 0    // Byte = 0
val a: Double = 0  // Double = 0.0
val a: Float = 0   // Float = 0.0
val a: Int = 0     // Int = 0
val a: Long = 0    // Long = 0
val a: Short = 0   // Short = 0

val x = BigInt(1_234_456_789)
val y = BigDecimal(1_234_456.890)

ๅธƒๅฐ”ๅ€ผ

ไธคไธช่ฏญ่จ€้ƒฝๅœจๅธƒๅฐ”ๅ€ผไธญ็”จ true ๅ’Œ falseใ€‚

let a = true;
let b = false;
val a = true
val b = false

ๆ—ฅๆœŸ

ๆ—ฅๆœŸๆ˜ฏไธค็ง่ฏญ่จ€ไธญๅฆไธ€็งๅธธ็”จ็š„็ฑปๅž‹ใ€‚

่Žทๅ–ๅฝ“ๅ‰ๆ—ฅๆœŸ๏ผš

let d = new Date();

// result:
// Sun Nov 29 2020 18:47:57 GMT-0700 (Mountain Standard Time)
// different ways to get the current date and time
import java.time.*

val a = LocalDate.now
    // 2020-11-29
val b = LocalTime.now
    // 18:46:38.563737
val c = LocalDateTime.now
    // 2020-11-29T18:46:38.563750
val d = Instant.now
    // 2020-11-30T01:46:38.563759Z

ๆŒ‡ๅฎšไธๅŒ็š„ๆ—ฅๆœŸ๏ผš

let d = Date(2020, 1, 21, 1, 0, 0, 0);
let d = Date(2020, 1, 21, 1, 0, 0);
let d = Date(2020, 1, 21, 1, 0);
let d = Date(2020, 1, 21, 1);
let d = Date(2020, 1, 21);
val d = LocalDate.of(2020, 1, 21)
val d = LocalDate.of(2020, Month.JANUARY, 21)
val d = LocalDate.of(2020, 1, 1).plusDays(20)

ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒScala ไฝฟ็”จ Java ้™„ๅธฆ็š„ๆ—ฅๆœŸๅ’Œๆ—ถ้—ด็ฑปใ€‚ JavaScript ๅ’Œ Scala ไน‹้—ด็š„่ฎธๅคšๆ—ฅๆœŸ/ๆ—ถ้—ดๆ–นๆณ•ๆ˜ฏ็›ธไผผ็š„ใ€‚ ๆœ‰ๅ…ณ่ฏฆ็ป†ไฟกๆฏ๏ผŒ่ฏทๅ‚้˜… java.time ๅŒ…ใ€‚

ๅ‡ฝๆ•ฐ

ๅœจ JavaScript ๅ’Œ Scala ไธญ๏ผŒๅ‡ฝๆ•ฐ้ƒฝๆ˜ฏๅฏน่ฑก๏ผŒๅ› ๆญคๅฎƒไปฌ็š„ๅŠŸ่ƒฝ็›ธไผผ๏ผŒไฝ†ๅฎƒไปฌ็š„่ฏญๆณ•ๅ’Œๆœฏ่ฏญ็•ฅๆœ‰ไธๅŒใ€‚

ๅ‘ฝๅๅ‡ฝๆ•ฐ๏ผŒไธ€่กŒ๏ผš

function add(a, b) {
  return a + b;
}
add(2, 2);   // 4
// technically this is a method, not a function
def add(a: Int, b: Int) = a + b
add(2, 2)   // 4

ๅ‘ฝๅๅ‡ฝๆ•ฐ๏ผŒๅคš่กŒ๏ผš

function addAndDouble(a, b) {
  // imagine this requires
  // multiple lines
  return (a + b) * 2
}
def addAndDouble(a: Int, b: Int): Int =
  // imagine this requires
  // multiple lines
  (a + b) * 2

ๅœจ Scala ไธญ๏ผŒๆ˜พ็คบ Int ่ฟ”ๅ›ž็ฑปๅž‹ๆ˜ฏๅฏ้€‰็š„ใ€‚ ๅฎƒ_ไธ_ๆ˜พ็คบๅœจ add ็คบไพ‹ไธญ๏ผŒ่€Œ_ๆ˜ฏ_ๆ˜พ็คบๅœจ addAndDouble ็คบไพ‹ไธญ๏ผŒๅ› ๆญคๆ‚จๅฏไปฅ็œ‹ๅˆฐ่ฟ™ไธค็งๆ–นๆณ•ใ€‚

ๅŒฟๅๅ‡ฝๆ•ฐ

JavaScript ๅ’Œ Scala ้ƒฝๅ…่ฎธๆ‚จๅฎšไน‰ๅŒฟๅๅ‡ฝๆ•ฐ๏ผŒๆ‚จๅฏไปฅๅฐ†ๅ…ถไผ ้€’็ป™ๅ…ถไป–ๅ‡ฝๆ•ฐๅ’Œๆ–นๆณ•ใ€‚

็ฎญๅคดๅ’ŒๅŒฟๅๅ‡ฝๆ•ฐ

// arrow function
let log = (s) => console.log(s)

// anonymous function
let log = function(s) {
  console.log(s);
}

// use either of those functions here
function printA(a, log) {
  log(a);
}
// a function (an anonymous function assigned to a variable)
val log = (s: String) => console.log(s)

// a scala method. methods tend to be used much more often,
// probably because theyโ€™re easier to read.
def log(a: Any) = console.log(a)

// a function or a method can be passed into another
// function or method
def printA(a: Any, f: log: Any => Unit) = log(a)

ๅœจ Scala ไธญ๏ผŒๆ‚จๅพˆๅฐ‘ไฝฟ็”จๆ‰€็คบ็š„็ฌฌไธ€็ง่ฏญๆณ•ๆฅๅฎšไน‰ๅ‡ฝๆ•ฐใ€‚ ็›ธๅ๏ผŒๆ‚จ็ปๅธธๅœจไฝฟ็”จ็‚นๅฎšไน‰ๅŒฟๅๅ‡ฝๆ•ฐใ€‚ ่ฎธๅคš้›†ๅˆๆ–นๆณ•ๆ˜ฏ ้ซ˜้˜ถๅ‡ฝๆ•ฐๅนถๆŽฅๅ—ๅ‡ฝๆ•ฐๅ‚ๆ•ฐ๏ผŒๅ› ๆญคๆ‚จ็ผ–ๅ†™ๅฆ‚ไธ‹ไปฃ็ ๏ผš

// map method, long form
List(1,2,3).map(i => i * 10)   // List(10,20,30)

// map, short form (which is more commonly used)
List(1,2,3).map(_ * 10)        // List(10,20,30)

// filter, short form
List(1,2,3).filter(_ < 3)      // List(1,2)

// filter and then map
List(1,2,3,4,5).filter(_ < 3).map(_ * 10)   // List(10, 20)

็ฑป

Scala ๆ—ขๆœ‰็ฑปไนŸๆœ‰ๆ ทไพ‹็ฑปใ€‚ ็ฑป ไธŽ JavaScript ็ฑป็›ธไผผ๏ผŒ้€šๅธธ็”จไบŽ OOP ้ฃŽๆ ผๅบ”็”จ็จ‹ๅบ๏ผˆๅฐฝ็ฎกๅฎƒไปฌไนŸๅฏไปฅๅœจ FP ไปฃ็ ไธญไฝฟ็”จ๏ผ‰๏ผŒๅนถไธ” _ๆ ทไพ‹็ฑป_ๆœ‰้™„ๅŠ ็š„็‰นๆ€ง๏ผŒ่ฟ™่ฎฉๅฎƒๅœจ FP ้ฃŽๆ ผๅบ”็”จไธญๅพˆๆœ‰็”จใ€‚

ไธ‹้ข็š„ไพ‹ๅญๅฑ•็คบไบ†ๅฆ‚ไฝ•ๅˆ›ๅปบๅ‡ ไธช็ฑปๅž‹ไฝœไธบๆžšไธพ๏ผŒ็„ถๅŽๅฎšไน‰ไธ€ไธช OOP ้ฃŽๆ ผ็š„ Pizza ็ฑปใ€‚ ๆœ€ๅŽ๏ผŒๅˆ›ๅปบๅนถไฝฟ็”จไบ†ไธ€ไธช Pizza ๅฎžไพ‹๏ผš

// create some enumerations that the Pizza class will use
enum CrustSize:
  case Small, Medium, Large

enum CrustType:
  case Thin, Thick, Regular

enum Topping:
  case Cheese, Pepperoni, BlackOlives, GreenOlives, Onions

// import those enumerations and the ArrayBuffer,
// so the Pizza class can use them
import CrustSize.*
import CrustType.*
import Topping.*
import scala.collection.mutable.ArrayBuffer

// define an OOP style Pizza class
class Pizza(
  var crustSize: CrustSize,
  var crustType: CrustType
):

  private val toppings = ArrayBuffer[Topping]()

  def addTopping(t: Topping): Unit =
    toppings += t

  def removeTopping(t: Topping): Unit =
    toppings -= t

  def removeAllToppings(): Unit =
    toppings.clear()

  override def toString(): String =
    s"""
      |Pizza:
      |  Crust Size: ${crustSize}
      |  Crust Type: ${crustType}
      |  Toppings:   ${toppings}
    """.stripMargin

end Pizza

// create a Pizza instance
val p = Pizza(Small, Thin)

// change the crust
p.crustSize = Large
p.crustType = Thick

// add and remove toppings
p.addTopping(Cheese)
p.addTopping(Pepperoni)
p.addTopping(BlackOlives)
p.removeTopping(Pepperoni)

// print the pizza, which uses its `toString` method
println(p)

ๆŽฅๅฃใ€trait ๅ’Œ็ปงๆ‰ฟ

Scala ไฝฟ็”จ trait ไฝœไธบๆŽฅๅฃ๏ผŒไนŸๅฏไปฅๅˆ›ๅปบๆททๆญใ€‚ trait ๅฏไปฅๆœ‰ๆŠฝ่ฑกๅ’Œๅ…ทไฝ“็š„ๆˆๅ‘˜๏ผŒๅŒ…ๆ‹ฌๆ–นๆณ•ๅ’Œๅญ—ๆฎตใ€‚

่ฟ™ไธชไพ‹ๅญๅฑ•็คบไบ†ๅฆ‚ไฝ•ๅฎšไน‰ไธคไธช traits๏ผŒๅˆ›ๅปบไธ€ไธชๆ‰ฉๅฑ•ๅ’Œๅฎž็Žฐ่ฟ™ไบ› traits ็š„็ฑป๏ผŒ็„ถๅŽๅˆ›ๅปบๅ’Œไฝฟ็”จ่ฏฅ็ฑป็š„ไธ€ไธชๅฎžไพ‹๏ผš

trait HasLegs:
  def numLegs: Int
  def walk(): Unit
  def stop() = println("Stopped walking")

trait HasTail:
  def wagTail(): Unit
  def stopTail(): Unit

class Dog(var name: String) extends HasLegs, HasTail:
  val numLegs = 4
  def walk() = println("Iโ€™m walking")
  def wagTail() = println("โŽžโŽœโŽ›  โŽžโŽœโŽ›")
  def stopTail() = println("Tail is stopped")
  override def toString = s"$name is a Dog"

// create a Dog instance
val d = Dog("Rover")

// use the classโ€™s attributes and behaviors
println(d.numLegs)   // 4
d.wagTail()          // "โŽžโŽœโŽ›  โŽžโŽœโŽ›"
d.walk()             // "Iโ€™m walking"

ๆŽงๅˆถ็ป“ๆž„

้™คไบ†ๅœจ JavaScript ไธญไฝฟ็”จ === ๅ’Œ !== ไน‹ๅค–๏ผŒๆฏ”่พƒๅ’Œ้€ป่พ‘่ฟ็ฎ—็ฌฆๅœจ JavaScript ๅ’Œ Scala ไธญๅ‡ ไนŽ็›ธๅŒใ€‚

ๆฏ”่พƒ่ฟ็ฎ—็ฌฆ

JavaScript Scala
== ==
=== ==
!= !=
!== !=
> >
< <
>= >=
<= <=

้€ป่พ‘่ฟ็ฎ—็ฌฆ

JavaScript Scala
&&
||
!
&&
||
!

if/then/else ่กจ่พพๅผ

JavaScriptๅ’Œ Scala if/then/else ่ฏญๅฅ็›ธไผผใ€‚ ๅœจ Scala 2 ไธญๅฎƒไปฌๅ‡ ไนŽ็›ธๅŒ๏ผŒไฝ†ๅœจ Scala 3 ไธญ๏ผŒ่Šฑๆ‹ฌๅทไธๅ†ๆ˜ฏๅฟ…้œ€็š„๏ผˆๅฐฝ็ฎกๅฎƒไปฌไป็„ถๅฏไปฅไฝฟ็”จ๏ผ‰ใ€‚

if ่ฏญๅฅ๏ผŒๅ•่กŒ๏ผš

if (x == 1) { console.log(1); }
if x == 1 then println(x)

if ่ฏญๅฅ๏ผŒๅคš่กŒ๏ผš

if (x == 1) {
  console.log("x is 1, as you can see:")
  console.log(x)
}
if x == 1 then
  println("x is 1, as you can see:")
  println(x)

if, else if, else:

if (x < 0) {
  console.log("negative")
} else if (x == 0) {
  console.log("zero")
} else {
  console.log("positive")
}
if x < 0 then
  println("negative")
else if x == 0
  println("zero")
else
  println("positive")

ไปŽ if ่ฟ”ๅ›žๅ€ผ๏ผš

JavaScript ไฝฟ็”จไธ‰ๅ…ƒ่ฟ็ฎ—็ฌฆ๏ผŒScala ๅƒๅพ€ๅธธไธ€ๆ ทไฝฟ็”จๅฎƒ็š„ if ่กจ่พพๅผ๏ผš

let minVal = a < b ? a : b;
val minValue = if a < b then a else b

if ไฝœไธบๆ–นๆณ•ไฝ“๏ผš

Scala ๆ–นๆณ•ๅพ€ๅพ€ๅพˆ็Ÿญ๏ผŒๆ‚จๅฏไปฅ่ฝปๆพๅœฐไฝฟ็”จ if ไฝœไธบๆ–นๆณ•ไฝ“๏ผš

function min(a, b) {
  return (a < b) ? a : b;
}
def min(a: Int, b: Int): Int =
  if a < b then a else b

ๅœจ Scala 3 ไธญ๏ผŒๅฆ‚ๆžœๆ‚จๆ„ฟๆ„๏ผŒๆ‚จไป็„ถๅฏไปฅไฝฟ็”จโ€œ่Šฑๆ‹ฌๅทโ€ๆ ทๅผใ€‚ ไพ‹ๅฆ‚๏ผŒๆ‚จๅฏไปฅๅƒ่ฟ™ๆ ท็ผ–ๅ†™ if/else-if/else ่กจ่พพๅผ๏ผš

if (i == 0) {
  println(0)
} else if (i == 1) {
  println(1)
} else {
  println("other")
}

ๅพช็Žฏ

JavaScript ๅ’Œ Scala ้ƒฝๆœ‰ while ๅพช็Žฏๅ’Œ for ๅพช็Žฏใ€‚ Scala ๆ›พ็ปๆœ‰ do/while ๅพช็Žฏ๏ผŒไฝ†ๅฎƒไปฌๅทฒไปŽ่ฏญ่จ€ไธญๅˆ ้™คใ€‚

while ๅพช็Žฏ๏ผš

let i = 0;
while (i < 3) {
  console.log(i);
  i++;
}
var i = 0;
while i < 3 do
  println(i)
  i += 1

ๅฆ‚ๆžœไฝ ๆ„ฟๆ„๏ผŒScala ไปฃ็ ไนŸๅฏไปฅๅ†™ๆˆ่ฟ™ๆ ท๏ผš

var i = 0
while (i < 3) {
  println(i)
  i += 1
}

ไปฅไธ‹็คบไพ‹ๅฑ•็คบไบ† JavaScript ๅ’Œ Scala ไธญ็š„โ€œforโ€ๅพช็Žฏใ€‚ ไป–ไปฌๅ‡่ฎพๆ‚จๅฏไปฅไฝฟ็”จ่ฟ™ไบ›้›†ๅˆ๏ผš

// JavaScript
let nums = [1, 2, 3];

// Scala
val nums = List(1, 2, 3)

for ๅพช็Žฏ๏ผŒๅ•่กŒ๏ผš

// newer syntax
for (let i of nums) {
  console.log(i);
}

// older
for (i=0; i<nums.length; i++) {
  console.log(nums[i]);
}
// preferred
for i <- ints do println(i)

// also available
for (i <- ints) println(i)

for ๅพช็Žฏ๏ผŒๅœจๅพช็Žฏไฝ“ๅ†…ๅคš่กŒ

// preferred
for (let i of nums) {
  let j = i * 2;
  console.log(j);
}

// also available
for (i=0; i<nums.length; i++) {
  let j = nums[i] * 2;
  console.log(j);
}
// preferred
for i <- ints do
  val i = i * 2
  println(j)

// also available
for (i <- nums) {
  val j = i * 2
  println(j)
}

ๅœจ for ๅพช็Žฏไธญๆœ‰ๅคšไธช็”Ÿๆˆๅ™จ

let str = "ab";
for (let i = 1; i < 3; i++) {
  for (var j = 0; j < str.length; j++) {
    for (let k = 1; k < 11; k++) {
      let c = str.charAt(j);
      console.log(`i: ${i} j: ${c} k: ${k}`);
    }
  }
}
for
  i <- 1 to 2
  j <- 'a' to 'b'
  k <- 1 to 10 by 5
do
  println(s"i: $i, j: $j, k: $k")

ๅธฆๅฎˆๅซ็š„็”Ÿๆˆๅ™จ

_ๅฎˆๅซ_ๆ˜ฏ for ่กจ่พพๅผไธญ็š„ if ่กจ่พพๅผ็š„ๅ็งฐใ€‚

for (let i = 0; i < 10; i++) {
  if (i % 2 == 0 && i < 5) {
    console.log(i);
  }
}
for
  i <- 1 to 10
  if i % 2 == 0
  if i < 5
do
  println(i)

for comprehension

for comprehension ๆ˜ฏไธ€ไธช for ๅพช็Žฏ๏ผŒๅฎƒไฝฟ็”จ yield ่ฟ”ๅ›ž๏ผˆไบง็”Ÿ๏ผ‰ไธ€ไธชๅ€ผใ€‚ ๅฎƒไปฌ็ปๅธธๅœจ Scala ไธญไฝฟ็”จใ€‚

N/A
val list =
  for
    i <- 1 to 3
  yield
    i * 10
// result: Vector(10, 20, 30)

switch & match

JavaScript ๆœ‰ switch ่ฏญๅฅ๏ผŒScala ๆœ‰ match ่กจ่พพๅผใ€‚ ๅฐฑๅƒ Scala ไธญ็š„ๆ‰€ๆœ‰ๅ…ถไป–ไธœ่ฅฟไธ€ๆ ท๏ผŒ่ฟ™ไบ›็กฎๅฎžๆ˜ฏ_่กจ่พพๅผ_๏ผŒ่ฟ™ๆ„ๅ‘ณ็€ๅฎƒไปฌ่ฟ”ๅ›žไธ€ไธช็ป“ๆžœ๏ผš

val day = 1

// later in the code ...
val monthAsString = day match
  case 1 => "January"
  case 2 => "February"
  case _ => "Other"

match ่กจ่พพๅผๅฏไปฅๅœจๆฏไธช case ่ฏญๅฅไธญๅค„็†ๅคšไธชๅŒน้…้กน๏ผš

val numAsString = i match
  case 1 | 3 | 5 | 7 | 9 => "odd"
  case 2 | 4 | 6 | 8 | 10 => "even"
  case _ => "too big"

ๅฎƒไปฌไนŸๅฏไปฅ็”จไบŽๆ–นๆณ•ไฝ“๏ผš

def isTruthy(a: Matchable) = a match
  case 0 | "" => false
  case _ => true

def isPerson(x: Matchable): Boolean = x match
  case p: Person => true
  case _ => false

match ่กจ่พพๅผๆœ‰่ฎธๅคšๅ…ถไป–ๆจกๅผๅŒน้…้€‰้กนใ€‚

้›†ๅˆ็ฑป

Scala ๆœ‰ไธๅŒ็š„ ้›†ๅˆ็ฑป ๆฅๆปก่ถณไธๅŒ็š„้œ€ๆฑ‚ใ€‚

ๅธธ่ง็š„_ไธๅฏๅ˜_ๅบๅˆ—ๆ˜ฏ๏ผš

  • List
  • Vector

ๅธธ่ง็š„_ๅฏๅ˜_ๅบๅˆ—ๆ˜ฏ๏ผš

  • Array
  • ArrayBuffer

Scala ่ฟ˜ๆœ‰ๅฏๅ˜ๅ’Œไธๅฏๅ˜็š„ Map ๅ’Œ Setใ€‚

่ฟ™ๆ˜ฏๅˆ›ๅปบๅธธ่ง Scala ้›†ๅˆ็ฑปๅž‹็š„ๆ–นๅผ๏ผš

val strings = List("a", "b", "c")
val strings = Vector("a", "b", "c")
val strings = ArrayBuffer("a", "b", "c")

val set = Set("a", "b", "a") // result: Set("a", "b")
val map = Map(
  "a" -> 1,
  "b" -> 2,
  "c" -> 3
)

้›†ๅˆไธŠ็š„ๆ–นๆณ•

ไปฅไธ‹็คบไพ‹ๅฑ•็คบไบ†ไฝฟ็”จ Scala ้›†ๅˆ็š„่ฎธๅคšไธๅŒๆ–นๆณ•ใ€‚

ๅกซๅ……ๅˆ—่กจ๏ผš

// to, until
(1 to 5).toList                   // List(1, 2, 3, 4, 5)
(1 until 5).toList                // List(1, 2, 3, 4)

(1 to 10 by 2).toList             // List(1, 3, 5, 7, 9)
(1 until 10 by 2).toList          // List(1, 3, 5, 7, 9)
(1 to 10).by(2).toList            // List(1, 3, 5, 7, 9)

('d' to 'h').toList               // List(d, e, f, g, h)
('d' until 'h').toList            // List(d, e, f, g)
('a' to 'f').by(2).toList         // List(a, c, e)

// range method
List.range(1, 3)                  // List(1, 2)
List.range(1, 6, 2)               // List(1, 3, 5)

List.fill(3)("foo")               // List(foo, foo, foo)
List.tabulate(3)(n => n * n)      // List(0, 1, 4)
List.tabulate(4)(n => n * n)      // List(0, 1, 4, 9)

ๅบๅˆ—ไธŠ็š„ๅ‡ฝๆ•ฐๅผๆ–นๆณ•๏ผš

// these examples use a List, but theyโ€™re the same with Vector
val a = List(10, 20, 30, 40, 10)      // List(10, 20, 30, 40, 10)
a.contains(20)                        // true
a.distinct                            // List(10, 20, 30, 40)
a.drop(2)                             // List(30, 40, 10)
a.dropRight(2)                        // List(10, 20, 30)
a.dropWhile(_ < 25)                   // List(30, 40, 10)
a.filter(_ < 25)                      // List(10, 20, 10)
a.filter(_ > 100)                     // List()
a.find(_ > 20)                        // Some(30)
a.head                                // 10
a.headOption                          // Some(10)
a.init                                // List(10, 20, 30, 40)
a.last                                // 10
a.lastOption                          // Some(10)
a.slice(2,4)                          // List(30, 40)
a.tail                                // List(20, 30, 40, 10)
a.take(3)                             // List(10, 20, 30)
a.takeRight(2)                        // List(40, 10)
a.takeWhile(_ < 30)                   // List(10, 20)

// map, flatMap
val fruits = List("apple", "pear")
fruits.map(_.toUpperCase)             // List(APPLE, PEAR)
fruits.flatMap(_.toUpperCase)         // List(A, P, P, L, E, P, E, A, R)

val nums = List(10, 5, 8, 1, 7)
nums.sorted                           // List(1, 5, 7, 8, 10)
nums.sortWith(_ < _)                  // List(1, 5, 7, 8, 10)
nums.sortWith(_ > _)                  // List(10, 8, 7, 5, 1)

List(1,2,3).updated(0,10)             // List(10, 2, 3)
List(2,4).union(List(1,3))            // List(2, 4, 1, 3)

// zip
val women = List("Wilma", "Betty")    // List(Wilma, Betty)
val men = List("Fred", "Barney")      // List(Fred, Barney)
val couples = women.zip(men)          // List((Wilma,Fred), (Betty,Barney))

Scala ๆœ‰_ๅพˆๅคš_ๆ›ดๅคšๅฏไพ›ๆ‚จไฝฟ็”จ็š„ๆ–นๆณ•ใ€‚ ๆ‰€ๆœ‰่ฟ™ไบ›ๆ–นๆณ•็š„ๅฅฝๅค„ๆ˜ฏ๏ผš

  • ๆ‚จไธๅฟ…็ผ–ๅ†™่‡ชๅฎšไน‰็š„ for ๅพช็Žฏๆฅ่งฃๅ†ณ้—ฎ้ข˜
  • ๅฝ“ไฝ ้˜…่ฏปๅˆซไบบ็š„ไปฃ็ ๆ—ถ๏ผŒไฝ ไธๅฟ…้˜…่ฏปไป–ไปฌ่‡ชๅฎšไน‰็š„ for ๅพช็Žฏ๏ผ› ไฝ ๅชไผšๆ‰พๅˆฐๅƒ่ฟ™ๆ ท็š„ๅธธ็”จๆ–นๆณ•๏ผŒๅ› ๆญคๆ›ดๅฎนๆ˜“้˜…่ฏปๆฅ่‡ชไธๅŒ้กน็›ฎ็š„ไปฃ็ 

ๅ…ƒ็ป„

ๅฝ“ๆ‚จๆƒณๅฐ†ๅคšไธชๆ•ฐๆฎ็ฑปๅž‹ๆ”พๅœจๅŒไธ€ไธชๅˆ—่กจไธญๆ—ถ๏ผŒJavaScript ๅ…่ฎธๆ‚จ่ฟ™ๆ ทๅš๏ผš

stuff = ["Joe", 42, 1.0];

ๅœจ Scala ไธญไฝ ่ฟ™ๆ ทๅš๏ผš

val a = ("eleven")
val b = ("eleven", 11)
val c = ("eleven", 11, 11.0)
val d = ("eleven", 11, 11.0, Person("Eleven"))

ๅœจ Scala ไธญ๏ผŒ่ฟ™ไบ›็ฑปๅž‹็งฐไธบๅ…ƒ็ป„๏ผŒๅฆ‚ๅ›พๆ‰€็คบ๏ผŒๅฎƒไปฌๅฏไปฅๅŒ…ๅซไธ€ไธชๆˆ–ๅคšไธชๅ…ƒ็ด ๏ผŒๅนถไธ”ๅ…ƒ็ด ๅฏไปฅๅ…ทๆœ‰ไธๅŒ็š„็ฑปๅž‹ใ€‚ ่ฎฟ้—ฎๅฎƒไปฌ็š„ๅ…ƒ็ด ๅฐฑๅƒ่ฎฟ้—ฎ Listใ€Vector ๆˆ– Array ็š„ๅ…ƒ็ด ไธ€ๆ ท๏ผš

d(0)   // "eleven"
d(1)   // 11

ๆžšไธพ

JavaScript ๆฒกๆœ‰ๆžšไธพ๏ผŒไฝ†ไฝ ๅฏไปฅ่ฟ™ๆ ทๅš๏ผš

let Color = {
  RED: 1,
  GREEN: 2,
  BLUE: 3
};
Object.freeze(Color);

ๅœจ Scala 3 ไธญ๏ผŒๆ‚จๅฏไปฅไฝฟ็”จๆžšไธพๅšๅพˆๅคšไบ‹ๆƒ…ใ€‚ ๆ‚จๅฏไปฅๅˆ›ๅปบ่ฏฅไปฃ็ ็š„็ญ‰ๆ•ˆไปฃ็ ๏ผš

enum Color:
  case Red, Green, Blue

ไฝ ๅฏไปฅๅˆ›ๅปบๅธฆๅ‚ๆ•ฐ็š„ๆžšไธพ๏ผš

enum Color(val rgb: Int):
  case Red   extends Color(0xFF0000)
  case Green extends Color(0x00FF00)
  case Blue  extends Color(0x0000FF)

ไฝ ไนŸๅฏไปฅๅˆ›ๅปบ็”จๆˆท่‡ชๅฎšไน‰็š„ๆžšไธพๆˆๅ‘˜๏ผš

enum Planet(mass: Double, radius: Double):
  case Mercury extends Planet(3.303e+23, 2.4397e6)
  case Venus   extends Planet(4.869e+24,6.0518e6)
  case Earth   extends Planet(5.976e+24,6.37814e6)
  // more planets here ...

  private final val G = 6.67300E-11
  def surfaceGravity = G * mass / (radius * radius)
  def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity

Scala.js DOM ไปฃ็ 

Scala.js ๅ…่ฎธๆ‚จ็ผ–ๅ†™ Scala ไปฃ็ ๏ผŒ่ฟ™ไบ›ไปฃ็ ็ผ–่ฏ‘ไธบ JavaScript ไปฃ็ ๏ผŒ็„ถๅŽๅฏไปฅๅœจๆต่งˆๅ™จไธญไฝฟ็”จใ€‚ ่ฏฅๆ–นๆณ•็ฑปไผผไบŽ TypeScriptใ€ReScript ๅ’Œๅ…ถไป–็ผ–่ฏ‘ไธบ JavaScript ็š„่ฏญ่จ€ใ€‚

ๅŒ…ๅซๅฟ…่ฆ็š„ๅบ“ๅนถๅœจ้กน็›ฎไธญๅฏผๅ…ฅๅฟ…่ฆ็š„ๅŒ…ๅŽ๏ผŒ็ผ–ๅ†™ Scala.js ไปฃ็ ็œ‹่ตทๆฅไธŽ็ผ–ๅ†™ JavaScript ไปฃ็ ้žๅธธ็›ธไผผ๏ผš

// show an alert dialog on a button click
jQuery("#hello-button").click{() =>
  dom.window.alert("Hello, world")
}

// define a button and what should happen when itโ€™s clicked
val btn = button(
  "Click me",
  onclick := { () =>
    dom.window.alert("Hello, world")
  })

// create two divs with css classes, an h2 element, and the button
val content =
  div(cls := "foo",
    div(cls := "bar",
      h2("Hello"),
      btn
    )
  )

// add the content to the DOM
val root = dom.document.getElementById("root")
root.innerHTML = ""
root.appendChild(content.render)

่ฏทๆณจๆ„๏ผŒๅฐฝ็ฎก Scala ๆ˜ฏไธ€็ง็ฑปๅž‹ๅฎ‰ๅ…จ็š„่ฏญ่จ€๏ผŒไฝ†ๅœจไธŠ้ข็š„ไปฃ็ ไธญๆฒกๆœ‰ๅฃฐๆ˜Žไปปไฝ•็ฑปๅž‹ใ€‚ Scala ๅผบๅคง็š„็ฑปๅž‹ๆŽจๆ–ญ่ƒฝๅŠ›้€šๅธธไฝฟ Scala ไปฃ็ ็œ‹่ตทๆฅๅƒๆ˜ฏๅŠจๆ€็ฑปๅž‹็š„ใ€‚ ไฝ†ๅฎƒๆ˜ฏ็ฑปๅž‹ๅฎ‰ๅ…จ็š„๏ผŒๅ› ๆญคๆ‚จๅฏไปฅๅœจๅผ€ๅ‘ๅ‘จๆœŸ็š„ๆ—ฉๆœŸๆ•่Žท่ฎธๅคš็ฑป้”™่ฏฏใ€‚

ๅ…ถไป– Scala.js ่ต„ๆบ

Scala.js ็ฝ‘็ซ™ไธบๅฏนไฝฟ็”จ Scala.js ๆ„Ÿๅ…ด่ถฃ็š„ JavaScript ๅผ€ๅ‘ไบบๅ‘˜ๆไพ›ไบ†ๆžๅฅฝ็š„ๆ•™็จ‹้›†ใ€‚ ไปฅไธ‹ๆ˜ฏไป–ไปฌ็š„ไธ€ไบ›ๅˆๅง‹ๆ•™็จ‹๏ผš

Scala ็‹ฌๆœ‰็š„ๆฆ‚ๅฟต

Scala ไธญ่ฟ˜ๆœ‰ๅ…ถไป–ไธ€ไบ›ๆฆ‚ๅฟต็›ฎๅ‰ๅœจ JavaScript ไธญๆฒกๆœ‰็ญ‰ๆ•ˆ็š„ๆฆ‚ๅฟต๏ผš

  • ๅ‡ ไนŽๆ‰€ๆœ‰ไธŽไธŠไธ‹ๆ–‡ๆŠฝ่ฑก็›ธๅ…ณ็š„ไธœ่ฅฟ
  • ๆ–นๆณ•็‰นๆ€ง๏ผš
    • ๅคšไธชๅ‚ๆ•ฐๅˆ—่กจ
    • ่ฐƒ็”จๆ–นๆณ•ๆ—ถไฝฟ็”จๅ‘ฝๅๅ‚ๆ•ฐ
  • ไฝฟ็”จ trait ไฝœไธบๆŽฅๅฃ
  • ๆ ทไพ‹็ฑป
  • ไผด็”Ÿ็ฑปๅ’Œๅฏน่ฑก
  • ๅˆ›ๅปบ่‡ชๅทฑ็š„ๆŽงๅˆถ็ป“ๆž„ๅ’Œ DSL ็š„่ƒฝๅŠ›
  • match ่กจ่พพๅผๅ’ŒๆจกๅผๅŒน้…็š„้ซ˜็บงๅŠŸ่ƒฝ
  • for comprehension
  • ไธญ็ผ€ๆ–นๆณ•
  • ๅฎๅ’Œๅ…ƒ็ผ–็จ‹
  • ๆ›ดๅคš็š„ โ€ฆ

Contributors to this page: