์ด ๋ฌธ์ ๋ Fable์ ๋ํ Python ์ง์์ ๋ํ ํ ๋ก ์ ๋๋ค. ํ์ฌ Fable์์ ์ฌ์ฉํ๋ Babel AST๋ Python ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ ๋งํผ ๊ฐ๊น์ต๋๋ค. ํนํ ์ด์ ํด๋์ค๊ฐ ์ง์๋ฉ๋๋ค.
์ด๊ฒ์ด ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด POC๊ฐ ๋ง๋ค์ด์ก์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ค์์ ์ํํ๋ ค๋ฉด ๋ง์ ์์ ์ด ํ์ํฉ๋๋ค.
Expression ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ F#์์ ์๊ฐ์ ๋ฐ์ Python์ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. option
, result
, seq
, map
, list
(FrozenList๋ผ๊ณ ํจ), ์ฌ์ํจ๊ณผ ๊ฐ์ ๋ฐ์ดํฐ ์ ํ์ ์์ฒด ๊ตฌํ์ ์ ๊ณตํฉ๋๋ค. ํ๋ก์ธ์, ... ๋ฐ๋ผ์ Fable ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํด๋นํ๋ Python์ผ๋ก ์ ํฉํด์ผ ํฉ๋๋ค. Python์์๋ Expression์ ์ฌ์ฉํ์ฌ F#ish ์ฝ๋๋ฅผ ์ํํฉ๋๋ค. Fable์์๋ Expression์ ์ฌ์ฉํ์ฌ Python ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค.
int
๋ ์์์ ๊ธธ์ด๋ฅผ ๊ฐ์ต๋๋ค. ํธํ๋๋๋ก .NET(๋จธ์ ) ์ ํ์ ์๋ฎฌ๋ ์ดํธํด์ผ ํฉ๋๊น, ์๋๋ฉด Python int
์ ํ์ F# int๋ก ๋
ธ์ถํด์ผ ํฉ๋๊น?POC์ ์์ค ์ฝ๋๋ ํ์ฌ ์ฌ๊ธฐ์ ์์ต๋๋ค:
brew install [email protected]
๋ฅผ ์ค์นํฉ๋๋ค. ํ์ด์ฌ์ ์์คํ
์์ python
, python3
๋๋ ๋ ๋ค๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.python
๋ถ๊ธฐ๋ก ์ ํํฉ๋๋ค.dotnet fsi build.fsx library-py
dotnet fsi build.fsx test-py
QuickTest.fs
๋ฅผ ์์ฃผ ๊ฐ๋จํ F# ์ฝ๋๋ก ํธ์งํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ต์์ ๋๋ ํ ๋ฆฌ์์ dotnet fsi build.fsx quicktest
๋ฅผ ์คํํฉ๋๋ค.์ด์ Fable ๋ฐ Expression ์ฝ๋๋ฅผ ๋ชจ๋ ํธ์งํ ์ ์์ผ๋ฉฐ ํ์ํ ๋ ์์ ์ฝ๋๊ฐ ๋ค์ ์ปดํ์ผ๋ฉ๋๋ค. Fable ์ฝ๋๋ฅผ ์์ ํ ํ ์ฌ์ปดํ์ผ์ ํธ๋ฆฌ๊ฑฐํ๋ ค๋ฉด QuickTest.fs
์ ๋ํ ์ถ๊ฐ ์ ์ฅ์ด ํ์ํฉ๋๋ค. ํ์ด์ฌ ํ์ผ์ quicktest.py
๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ข์ ๋ฐ๋ชจ๋ vscode์์ F#, JS ๋ฐ Python์ ๋์์ ๋ณด๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ฉด F# ํ์ผ์ ์ ์ฅํ ๋ ์ฝ๋๊ฐ ์ด๋ป๊ฒ ๋ณํ๋๋์ง ํ์ธํ ์ ์์ต๋๋ค.
ํฐ๋ฏธ๋์์ ์์ฑ๋ Python ์ฝ๋๋ฅผ ์คํํ ์ ์์ต๋๋ค.
$ python3 quicktest.py
๋ช ๊ฐ์ง ๊ด๋ จ ๋งํฌ:
ํ ๋ก , ์๊ฒฌ, ์์ด๋์ด ๋ฐ ์ฝ๋๋ก ์์ ๋กญ๊ฒ ๊ธฐ์ฌํ์ญ์์ค ๐
๋ฉ์ง ์ํ์ ๋๋ค @dbattli! ๐ ๐ ๐ Fable์ ์๋ ์์ด๋์ด๋ F#์ ๋ค๋ฅธ ์ธ์ด๋ก ์ฝ๊ฒ ์ปดํ์ผํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ ๊ฒ์ด์์ต๋๋ค. ์ข๋ ๋์๋ Fable์ JS๋ฅผ ์ฃผ์ ์ด์ ์ผ๋ก ๋ฐ์ ์์ผ ์๊ธฐ ๋๋ฌธ์ ์ธ์ด์ ๊ตฌ์ ๋ฐ์ง ์๊ฒ ํ๋ ค๋ฉด ์ฝ๊ฐ์ ์์ ์ด ํ์ํ์ง๋ง ์ด์ ๋ํด ๊ฐ๋ฐฉ์ ์ ๋๋ค. ๊ทํ์ ์ง๋ฌธ์ ๋ํ ๋ช ๊ฐ์ง ์๊ฒฌ:
๊ฐ๊ฑฐ๋ ๋ค๋ฅธ repo? ๊ฐ๋ฅํ ํ ๋ง์ ๊ณตํต ์ฝ๋๋ฅผ ์ ์งํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๋ค๋ฅธ ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋งค์ฐ ๋น ๋ฅด๊ฒ ๋ถ๊ธฐํ ์ ์์ง๋ง(์ธ์ฉ ์ง์์ผ๋ก ๋ถ๊ธฐ๋ฅผ ๋๊ธฐํํ๊ธฐ๊ฐ ์ด๋ฏธ ์ด๋ ต์ต๋๋ค) ๋์ ์ธ์ด์ ๋ฐ๋ผ ๋ชจ๋ ๊ณณ์์ ์กฐ๊ฑด์ด ๋ฐ์ํ์ง ์๋๋ก ์ฝ๋๋ฅผ ์ถฉ๋ถํ ๋ชจ๋ํํด์ผ ํฉ๋๋ค. ์ค๊ฐ ์๋ฃจ์ ์ Fable "Nucleus"(Core ๐๋ฅผ ์ฌ์ฉํ ์ ์์)์ ๊ฐ๋ฅํ ํ ๋ง์ ์ฝ๋๋ฅผ ์ถ์ถํ ๋ค์ ์ธ์ด ๊ตฌํ์ ๋ํด ๋ค๋ฅธ ์ ์ฅ์๋ฅผ ๊ฐ๋ ๊ฒ์ ๋๋ค.
Babel AST: ์ด๊ฒ์ ์๋ ์ฐ๋ฆฌ๊ฐ ์ฝ๋ ์ธ์๋ฅผ ์ํด Babel์ ์์กดํ๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ๋์์ต๋๋ค. ์ด์์ ์ธ ์ธ๊ณ์์๋ ์ด์ ํ๋ฆฐํฐ๊ฐ ์์ผ๋ฏ๋ก ์ ๊ฑฐํ ์ ์์ด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ Fable-to-Babel ๋จ๊ณ์์ ๋ง์ ์ผ์ด ์ผ์ด๋๊ธฐ ๋๋ฌธ์ ์ด๋ ค์ธ ๊ฒ์ ๋๋ค. ๊ฐ์ ์ด์ ๋ก ์ด ๋จ๊ณ์์ ๊ฐ๋ฅํ ํ ๋ง์ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด ๋ฐ๋์งํ ๊ฒ์ ๋๋ค. ์๋ง๋ Babel AST๋ฅผ ๋น๊ธฐ๋ฅ์ ์ธ์ด์ ๋ํด ์ข ๋ ์ผ๋ฐ์ ์ธ ๊ฒ์ผ๋ก ๋ง๋ค ์ ์์ ๊ฒ์ ๋๋ค. ๋ช ๊ฐ์ง ์:
F#์ ๋ Pythonicํ๊ฒ ๋ง๋์๊ฒ ์ต๋๊น? Fable์ ์ฌ์ฉํ๋ฉด ์ค๋ฒํค๋๋ฅผ ํผํ๊ธฐ ์ํด .NET ์๋ฏธ ์ฒด๊ณ๊ฐ ๋๋๋ก ํฌ์๋๋ ๊ท ํ์ ์ฐพ๊ธฐ ์ํด ํญ์ ๋
ธ๋ ฅํ์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ฐ๋ฆฌ๋ int์ ๋ํด ํน์ ์ ํ์ ์ฌ์ฉํ๋ ๋์ JS ๋ฒํธ๋ฅผ ์ฌ์ฉํฉ๋๋ค(long์ ๋ํด ๊ทธ๋ ๊ฒ ํ์ง๋ง). ์ด๊ฒ์ Python int
์ ์ฉ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์๋ฅผ ๋ค์ด ์ ์ ๋๋๊ธฐ ๋๋ ๋ช
์์ ์ซ์ ๋ณํ๊ณผ ๊ฐ์ ์๊ธฐ์น ์์ ๊ฒฐ๊ณผ๋ฅผ ํผํ๊ธฐ ์ํด ํน์ ์ง์ ์์ .NET ์๋ฏธ ์ฒด๊ณ๋ฅผ ์กด์คํ๊ธฐ ์ํด ๋ง์ ๊ธฐ์ฌ๋ฅผ ํ์ต๋๋ค.
์ด์จ๋ "๋ ํ์ด์ฌ์ ์ธ"์ด๋ผ๊ณ ๋งํ๋ฉด ์ฝ๋ ์คํ์ผ ๋๋ ๊ธฐ๋ณธ API๋ฅผ ์๋ฏธํฉ๋๊น? Fable์ ๋๋ถ๋ถ์ .NET BCL์ ์ง์ํ๋ ค๊ณ ํ์ง ์์ง๋ง ๊ฒฐ๊ตญ ๊ฐ๋ฐ์๊ฐ ์ต์ํ๊ฒ ์ฌ์ฉํ๋ ๊ณตํต ๊ธฐ๋ฅ/์ฐ์ฐ์๋ฅผ ์ง์ํด์ผ ํฉ๋๋ค(์ ๊ท ์ฌ์ฉ์๋ ํํ ๋ฆฌ์ผ์์ ์ฐพ์ ์ ์๊ธฐ ๋๋ฌธ์). ์ด๋ค ๊ฒฝ์ฐ์๋ ๊ธฐ๋ณธ API๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ต์
์ ์ ๊ณตํ๋ ๊ฒ์ด ์ข์ต๋๋ค( ๊ทธ๋ฐ ์๋ฏธ์์ Fable.Extras ๋ ์ข์ ์์ง์์
๋๋ค). ์๋ฅผ ๋ค์ด JS.console.log
์ผ๋ฐ์ ์ผ๋ก printfn
๋ณด๋ค ๊ฐ์ฒด์ ํ์์ ์ง์ ํ์ง๋ง ๊ฐ๋ฐ์๊ฐ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ํ์๋ฅผ ์ง์ํด์ผ ํฉ๋๋ค.
๋๋ ์ด ์์ด๋์ด๋ฅผ ์ข์ํ๋ค. ํนํ F#์์ Python ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ธฐ๋ฅผ ๊ณ ๋ํ๊ณ ์์ต๋๋ค. ์ด์์ ์ผ๋ก๋ ์์ Python ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋ SciSharp๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ต์ ์ด ์์ด์ผ ํฉ๋๋ค. Python๊ณผ ๊ฑฐ์ ๋์ผํ API๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝํฅ์ด ์์ต๋๋ค(Python ๋๋ .NET ์ปจํ ์คํธ์์ ์คํ๋๋ ๋์ผํ F# ์ฝ๋!)
์ด๋ฌํ F# ์ฝ๋๋ Fable์ ์ฌ์ฉํ์ฌ Python์ผ๋ก ์ปดํ์ผํ ๋ค์ Notebooks ์ปค๋(Jupyter ๋๋ .NET Interactive) ๋ด์์ ์ฌ์ฉํ์ฌ ๋ถ์ ์ํฌํ๋ก๋ฅผ ์ค์ ๋๋ฉ์ธ ์ค์ฌ ๊ธฐ๋ฅ์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค(์ด ๋ชจ๋ ๊ฒ์ "์ฃฝ์ด๋ ๊ธฐ๋ฅ"์ผ๋ก ๊ฐ์ฃผํ ์ ์์).
.NET Interactive๋ ํ์ฅ์ฑ์ด ๋งค์ฐ ๋ฐ์ด๋ F# ์ปค๋ ๋ด์์ Fable์ ์คํํ๋ ๊ฒ์ ๋งค์ฐ ์ฝ์ต๋๋ค(์์ ์ค์ธ PoC๊ฐ ์์ต๋๋ค).
๋ ๋ค๋ฅธ ์ ์ MS๊ฐ ๊ณง ์ ์ฒด .NET์ ๋ํด ์ ์ฌํ ์กฐ์ฉํ ๊ฒ์ ๊ณต๊ฐํ ๊ฒ์ด๋ผ๊ณ ์์ธกํ๋ค๋ ๊ฒ์ ๋๋ค(์์ธก์ .NET Interactive๊ฐ ๋ค๋ฃจ๋ ํ๋๊ณผ ๋ชฉํ์๋ง ๊ธฐ๋ฐํ๋ฏ๋ก ํ๋ฆด ์ ์์). ๊ทธ๋ค์ด ๊ทธ๋ ๊ฒ ํ๋ ๊ฒฝ์ฐ์๋ ์ฐ๋ฆฌ๋ Fable์ด ๊ธฐ๋ฅ์ ์ธ๊ณ์์ ์์ ํ JS/F#/Python ๋ฌด๊ธฐ๊ณ ๋ฅผ ๊ฐ๊ธฐ ์ํด ๋ณ๋๋ก ๊ทธ๊ฒ์ ๊ฐ๊ธฐ๋ฅผ ์ํฉ๋๋ค. MS ์ ๊ทผ ๋ฐฉ์์ Blazor-flavour์ ๋ ๋น์ทํ ๊ฒ์ ๋๋ค(๋ด ์๊ฐ์).
๊ฐ์ฌํฉ๋๋ค. ์ด๊ฒ์ @alfonsogarciacaro , @PawelStadnicki์ ๋ํ ํ๋ฅญํ ํผ๋๋ฐฑ์ ๋๋ค. ๋ด ๋ง์ ํ๋ก๊ทธ๋๋จธ๊ฐ .NET์ ๋ค์ ๊ตฌํํ๋ ๋์ Python ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฅผ ๋ ๋ง์ด ๋ ธ์ถํ์ฌ "Python" ๋๋์ ๊ฐ๊ฒ ํ๋ ค๋ ๊ฒฝ์ฐ์์ต๋๋ค(๊ทธ๋ฌ๋ฉด .NET์ ๋์ ์ฌ์ฉํด์ผ ํจ).
๋๋ ์ฐ๋ฆฌ๊ฐ ๋ ์ธ๊ณ์์ ๊ฐ์ฅ ์ข์ ๊ฒ์ ๊ฐ์ง ์ ์๊ณ ๋ฌด์์ ๊ฐ์ ธ์ฌ์ง ์ฌ์ฉ์๊ฐ ๊ฒฐ์ ํ๋๋ก ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค(์: Python์์ datetime
๋๋ .NET์์ DateTime
). ๋ฐ๋ผ์ ๊ฒฐ์ ํ ํ์๊ฐ ์์ผ๋ฉฐ ๊ฐ์ฅ ์ํ๋ ๊ฒ์ ๊ตฌํํ๋ฉด ๋ฉ๋๋ค(์ฃผ๋ฌธํ). ๊ทธ๋ฌ๋ ๋๋ ๊ฐ์ ๋ฌธ์ ๊ฐ Fable JS์ ๊ด๋ จ์ด ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์น ์ฑ์ ๊ตฌํํ๊ณ ์์ผ๋ฉฐ ๋ชจ๋ .NET์ ์ฌ์ฉํ ์ ์์ ๊ฒ์ผ๋ก ๊ธฐ๋ํ์ง๋ ์์ ๊ฒ์
๋๋ค. JS ์ํ๊ณ์ ๋ ์ ์ ๊ทผํ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ ๋ฏธ๋ฆฌ ๊ฒฐ์ ํ ํ์๊ฐ ์์ต๋๋ค. ์๋งค๋ฅผ ๊ฑท์ด๋ถ์ด๊ณ ์์ํด ๋ด ์๋ค ๐ Fable์ ์ผ๋ถ๊ฐ ๋์ด ์ด ๋ฌธ์ ๋ฅผ ํตํด ๋ณํ ๋ฑ์ ๋ํด ์ง๋ฌธํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๋ฐฐ์ธ ๊ฒ์ด ๋ง์ต๋๋ค.
์ถ์ : Expression btw์๋ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ ์ ์๋ ๊ผฌ๋ฆฌ ํธ์ถ ๋ฐ์ฝ๋ ์ดํฐ๋ ์์ต๋๋ค(๋๊ธฐํ ๋ฐ ๋น๋๊ธฐํ ๋ชจ๋). ๋ค์์ aioreactive์์ ์ฌ์ฉํ๋ ์ ์ ๋๋ค.
#1601์ด ์๊ฐ๋๋ค์.
Fable์ ํ์ฌ ๋ฐฑ์๋ "ํ๋ฌ๊ทธ์ธ"(LLVM์ ์๊ฐํ์ง๋ง F#์๋ง ํด๋น)์ผ๋ก ์ํํ ์ ์์ ๋งํผ ๊ฐ๋ ฅํ๊ฒ ๋ง๋๋ ์ข์ ๋ฐฉ๋ฒ์ด ์๋์ง ๊ถ๊ธํฉ๋๋ค. ๋ฌดํํ ๊ฐ๋ฅ์ฑ.
Babel AST๋ฅผ ์ข ๋ ์ผ๋ฐ์ ์ด๊ณ ํ์ํํ์ฌ C์ ๊ฐ์ ์ธ์ด๋ก ์ฝ๊ฒ ๋ณํ/์ธ์ํ ์ ์๋๋ก ๋ ธ๋ ฅํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ Fable์ ๊ฐ๋ฐํ๋ ๋์ ๋ฐฐ์ด ๊ฒ์ด ์๋ค๋ฉด ๊ฐ๋จํ F#์์ ๋ค๋ฅธ ์ธ์ด๋ก์ ์ปดํ์ผ๋ฌ๋ฅผ ์์ฑํ๋ ๊ฒ์ด (์ด๋ ์ ๋) ์ฝ์ง๋ง ์ข์ ๊ฐ๋ฐ ๊ฒฝํ๊ณผ ํตํฉ์ ์ ๊ณตํ๋ฏ๋ก F#์ ์ฅ์ ์ ์ธ๊ตญ ์ํ๊ณ๋ ๋ชจ๊ตญ์ด๋ก ๊ฐ๋ฐํ๋ ๊ฒ๋ณด๋ค ๋ ๋ฌด๊ฒ์ต๋๋ค.
@alfonsogarciacaro๊ฐ ๋งํ ๊ฒ. ๊ทธ ๊ณผ์ ์ ์ผ๋ถ๋ Fable BCL ๊ตฌํ์ F#์ผ๋ก ๋ ๋ง์ด ๋ง์ด๊ทธ๋ ์ด์ ํ์ฌ ๋ชจ๋ ์ธ์ด์ ๋ํด ๋ค์ ์์ฑํ ํ์๊ฐ ์๋๋ก ํ๋ ๊ฒ์ ๋๋ค.
ํฅ๋ฏธ๋ก์ด. Fable BCL ๊ตฌํ์ ์๋น ๋ถ๋ถ์ด (์๋ง๋) Javascript๋ก ์์ฑ๋์๋ค๋ ์ฌ์ค์ ๋ชฐ๋์ต๋๋ค. ๋๋ ๊ทธ๊ฒ์ด ์ด๋ฏธ ๋ ๋ง์ F#์ผ ๊ฒ์ด๋ผ๊ณ ๊ฐ์ ํ๋ค. ์ฌ๊ธฐ์๋ ๊ทธ๋ด๋งํ ์ด์ ๊ฐ ์๋ค๊ณ ์์ฌํ์ง ์์ต๋๋ค. ์ ๊ทธ๋ ๊ฒ ํ๋ ๊ฒ์ด ๋ ์ฌ์์ก์๊น์?
@jwosty ๋๋ต์ ์ฑ๋ฅ์์ ์ด์ ๋ก F# ์ ํ๊ณผ ๋ธ๋ผ์ฐ์ ์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์๋๋ ์ ํ ๊ฐ์ ์ฐจ์ด๋ฅผ ์ฐ๊ฒฐํ๊ณ ์์ฑ๋ ์ฝ๋๋ฅผ JavaScript ์์ฝ์์คํ ๋ด์์ ๋ ์ ํตํฉํ๊ธฐ ์ํ ๊ฒ์ ๋๋ค.
๋ํ .NET BCL
์๋ FSharp.Core
์ธ์๋ ๋งค์ฐ ํฐ API ํ๋ฉด์ด ์์ผ๋ฏ๋ก ๋ ํฐ ํ ์์ด๋ ์ด ๋
ธ๋ ฅ์ ์ ์งํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค. ๋๋๊ณ ์นญ์ฐฌํ ๋งํ๋ค).
๋ด๊ฐ ๋งํ๋ ค๋ ๊ฒ์ ๊ธฐ์ฌ(๋ฐ ์์ด๋์ด)๊ฐ ๋งค์ฐ ํ์๋ฐ๊ณ ๊ฐ์ฌํ๋ค๋ ๊ฒ์ ๋๋ค.
(๊ทธ๋ ๊ฒ ์งง์ง ์์) ๋๋ต์ ์ฑ๋ฅ์์ ์ด์ ๋ก, F# ์ ํ๊ณผ ๋ธ๋ผ์ฐ์ ์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์๋๋ ์ ํ ๊ฐ์ ์ฐจ์ด๋ฅผ ์ฐ๊ฒฐํ๊ณ ์์ฑ๋ ์ฝ๋๋ฅผ JavaScript ์์ฝ์์คํ ๋ด์์ ๋ ์ ํตํฉํ๊ธฐ ์ํ ๊ฒ์ ๋๋ค.
๋๋ ๊ทธ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
๋ด๊ฐ ๋งํ๋ ค๋ ๊ฒ์ ๊ธฐ์ฌ(๋ฐ ์์ด๋์ด)๊ฐ ๋งค์ฐ ํ์๋ฐ๊ณ ๊ฐ์ฌํ๋ค๋ ๊ฒ์ ๋๋ค.
ํ์คํ! ์ด๋งํผ ํฌ๊ณ ์ค์ํ ํ๋ก์ ํธ๋ฅผ ์ ์งํ๊ธฐ ์ํด ์ผ๋ง๋ ๋ง์ ๋ ธ๋ ฅ์ ๊ธฐ์ธ์ด๊ณ ์๋์ง ์ดํดํ๊ณ ์ฌ๋ฌ๋ถ์ด ์์ ํผ์ ๋๋ฌผ์ ์ง์ฌ์ผ๋ก ๊ฐ์ฌ๋๋ฆฝ๋๋ค. Fable์ ์ต๊ทผ์ ์ ์๊ฒ ๋งค์ฐ ์ ์ฉํ๊ณ ๋๋ ค๋๋ฆฌ๊ณ ์ถ์ต๋๋ค.
์ฝ๊ฐ์ ๋์์ ๋ฐ์ ์ ์์ต๋๋ค. ํ์ฌ ๊ฐ๋ฐ์ ์ํด QuickTest ํ๋ก์ ํธ๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค(์: dotnet fsi build.fsx quicktest
). ๊ฐ๋ฐํ๋ ๋์ Babel AST๋ฅผ ์ด๋ป๊ฒ ์ธ์ํฉ๋๊น? ( ์
๋ฐ์ดํธ : ASTViewer ๋ฅผ ์ฐพ์
๋ด ํ์ฌ ๋ฌธ์ ๋ Python์ด ์ฌ๋ฌ ์ค ๋๋ค(ํ์ดํ ํจ์)๋ฅผ ์ง์ํ์ง ์์ผ๋ฏ๋ก ๋๋ค๊ฐ ๋ช ๋ช ๋ ํจ์๋ก ๋ณํ ๋ฐ ์ถ์ถ๋๊ณ ๋์ ํด๋น ํจ์๋ฅผ ํธ์ถํด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค. ์ฌ๊ธฐ์ ์๋ ๋ชจ๋ ํ์ ์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค. ์:
let fn args cont =
cont args
let b = fn 10 (fun a ->
a + 1
)
๋ค์์ผ๋ก ๋ณํํด์ผ ํฉ๋๋ค.
let fn args cont =
cont args
let cont a =
a + 1
let b = fn 10 cont
ํจ์ ํธ์ถ์ args๋ก ๋ณํํ ๋ ๋ ๋์ ์์ค์์ ๋์ฒดํด์ผ ํ๊ฑฐ๋ if true then ...
๊ฐ์ ์ผ์ข
์ ๋ธ๋ก ๋ช
๋ น๋ฌธ์ ์ฌ์ฉํด์ผ ํ๊ธฐ ๋๋ฌธ์ ํ๋์ ํธ์ถ ํํ์์ ์ฌ๋ฌ ๋ช
๋ น๋ฌธ์ผ๋ก ๋์ฒดํ ๋ ์ด๋ป๊ฒ ์๊ฐํด์ผ ํ ๊น์?
@dbragtli ์์ฑ ์ค ์ผ๋ถ๋ ์ธ์ํ๋ ์ด ํ๋ฆฐํฐ ๋ ์ฐธ์กฐํ์ญ์์ค.
Fable BCL ๊ตฌํ์ ์๋น ๋ถ๋ถ์ด (์๋ง๋) Javascript๋ก ์์ฑ๋์๋ค๋ ์ฌ์ค์ ๋ชฐ๋์ต๋๋ค. ๋๋ ๊ทธ๊ฒ์ด ์ด๋ฏธ ๋ ๋ง์ F#์ผ ๊ฒ์ด๋ผ๊ณ ๊ฐ์ ํ๋ค. ๊ทธ๋ด๋งํ ์ด์ ๊ฐ ์๋ค๊ณ ๋ฏฟ์ด ์์ฌ์น ์์ต๋๋ค. ์ ๊ทธ๋ ๊ฒ ํ๋ ๊ฒ์ด ๋ ์ฌ์์ก์๊น์?
๋ค, @ncave๊ฐ ๋งํ๋ฏ์ด ์ฃผ๋ ์ด์ ๋ ๋ ๋ง์ ํ์ค JS๋ฅผ ์์ฑํ๋ ๊ฒ์ด์์ต๋๋ค. ์๋ฅผ ๋ค์ด, Funscript์์๋ ๋ชจ๋ FSharp.Core ๊ต์ฒด๊ฐ F#์ผ๋ก ์์ฑ๋์์ง๋ง Fable์์๋ ๊ฐ๋ฅํ๋ฉด JS ํ์ค๊ณผ ํตํฉํ๊ณ ์ถ์์ต๋๋ค(์: .NET IEnumerable ๋์ JS ๋ฐ๋ณต๊ธฐ ์ฌ์ฉ). ์ฒ์์๋ JS/Typescript๋ก ์์ฑํ๋ ๊ฒ์ด ๋ ์ฌ์ ์ต๋๋ค. ์ฒ์์๋ ์ฐํ-๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ JS ํ๋ก์ ํธ์์ ์ฌ์ฉํ ์ ์๋ ๋ณ๋์ ํจํค์ง๋ก ํผ๋ธ๋ฆฌ์ฑํ ์๊ฐ๋ ์์์ง๋ง ๊ธ์ธ ํ๊ธฐํ์ต๋๋ค.
Fable 2์์ ์ฐ๋ฆฌ๋ ์ผ๋ถ ๋ชจ๋์ F#์ผ๋ก ์ด์ํ๊ธฐ ์ํ ๋ ธ๋ ฅ์ ์์ํ์ต๋๋ค. ์ด๊ฒ์ dogfooding์ ์ฆ๊ฐ์ํค๊ณ FSharp.Core์ ๊ฐ์ ์ฌํญ์ ์ฝ๊ฒ ์ฌ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ๋งค์ฐ ์ ์ตํ์ต๋๋ค(์ต๊ทผ ๋งต ๋ฐ ์ธํธ์ ๋ง์ฐฌ๊ฐ์ง๋ก). ๊ทธ๋ฌ๋ ๋ญ๊ณผ ๊ณ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ฌ๊ธฐ ์ ๊ธฐ์ ์ฌ์ ํ ๋ช ๊ฐ์ง ํดํน์ด ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ต์ฒด ๋ชจ๋์ธ ํฐ ๊ดด๋ฌผ์ ๋ํด์๋ ์ด์ผ๊ธฐํ์ง ์๊ฒ ์ต๋๋ค. :)
๋ํ @ncave๊ฐ ๋งํ๋ฏ์ด ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ์ง ๊ด๋ฆฌํ๋ ๊ฒ์ ์์ฒญ๋ ์ผ์ด๊ธฐ ๋๋ฌธ์ ์ ์ง ๊ด๋ฆฌ ํ๋ฉด์ ์ค์ด๊ธฐ ์ํด ํญ์ BCL์ ๋ํ ์ง์์ ๋๋ฆฌ๋ ๊ฒ์ ๊บผ๋ คํ์ง๋ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฌ๋ฌ ๊ฐ์ง ํฐ ๊ณตํ์ด ์๋ค๋ ๊ฒ์ ๋งค์ฐ ์ด์ด ์ข์์ต๋๋ค. ์ฒ์๋ถํฐ.
@dbrattli AST ์ธ์์ ๋ํด Fable repo์์ ASTViewer ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ง ์์์ง ์ค๋๋์์ต๋๋ค. ๋ ๋์ ์ต์
์ @ncave ๋๋ F# AST๋ฅผ ๊ฒ์ฌํด์ผ ํ ๋ ์ต๊ทผ์ ์ฌ์ฉํ๋ Fantomas ์๊ฐํ ๋์ฐ๋ฏธ๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฒ์
๋๋ค( Show Typed AST ๋ฅผ ์ ํํด์ผ ํฉ๋๋ค). ๋ถํํ๋ ์ฐ๋ฆฌ๋ ์์ง Fable ๋๋ Bable AST์ ๋ํ ํน์ ํ๋ฆฐํฐ๋ฅผ ๊ฐ์ง๊ณ ์์ง ์์ต๋๋ค. Fable AST์ ๊ฒฝ์ฐ ๊ทธ๋ฅ ํฉ์งํฉ์ด๊ณ ๊ฐ๋จํ printfn "%A"
์๋ํ์ง๋ง ์์น ์ ๋ณด๊ฐ ์ฝ๊ฐ ์๋๋ฝ์ต๋๋ค.
๋๋ค ์ถ์ถ์ ๋ํด. ๊ฐ๋ฅํ์ง๋ง ์ฝ๊ฐ์ ์์ ์ด ํ์ํฉ๋๋ค. ๊ฐ์ ธ์ค๊ธฐ์ ์ ์ฌํ ์์ , ์ฆ AST๋ฅผ ํ์ํ ๋ ์์งํ๊ณ ๊ณ ์ ํ ์๋ณ์๋ฅผ ํ ๋นํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋์ค์ ์ฐ๋ฆฌ๋ ํ์ผ์ ๋งจ ์์ ํจ์๋ฅผ ์ ์ธ ํ ์ ์์ต๋๋ค. ์ฃผ์ ๋ฌธ์ ๋ ์บก์ฒ๋ ๊ฐ์ผ ๊ฒ์ ๋๋ค. F# AST์ ์ด์ ๋ํ ์ ๋ณด๊ฐ ์๋์ง ๊ธฐ์ต๋์ง ์์ง๋ง, ์ ๋ณด๊ฐ ์๋๋ผ๋ ๋ถํํ๋ AST์ ๋ณด๊ดํ์ง ์์ผ๋ฏ๋ก ๋ค์์ ์ํํด์ผ ํฉ๋๋ค. ์ธ์(๋๋ ๋๋ค ๋ด์ ๋ฐ์ธ๋ฉ)์ ํด๋นํ์ง ์๋ ๋๋ค ๋ณธ๋ฌธ์ ์ฌ์ฉ๋ ๋ชจ๋ idents๋ฅผ ์ฐพ์ ๋๋ค์ ์ถ๊ฐ ์ธ์๋ก ๋ณํํฉ๋๋ค.
@alfonsogarciacaro ์ข์ ์ ๋ณด ๊ฐ์ฌํฉ๋๋ค. ์ ์ฒซ PoC๋ Babel.fs
/ Fable2Babel.fs
, BabelPrinter.fs
๋ฑ์ ๋ณ๊ฒฝํ์ต๋๋ค. ์ด์ ๋ณ๋์ Python AST ์ฆ Python.fs
์ฒ์๋ถํฐ ์์ํ์ต๋๋ค PythonPrinter.fs
. ๊ทธ๋ฐ ๋ค์ Fable AST์์ ๋ณํํ๋ ๊ฒ๋ณด๋ค ์ฌ์ธ ์ ์์ผ๋ฏ๋ก Babel AST์์ Python AST๋ก ๋ณํํ๊ธฐ ์ํด Babel2Python.fs
๋ฅผ ์ถ๊ฐํ๋ ค๊ณ ํฉ๋๋ค Fable2Python.fs
์ด๋ ค์ด). ์ด๋ ๊ฒ ํ๋ฉด ๊ธฐ์กด ์ฝ๋ ๊ธฐ๋ฐ์ ๋๋ฌด ๋ง์ด ๋ง์ง์ง ์๊ณ ๋๋ค ์ฌ์์ฑ์ ์๋ํ ๋๋ง์ ๋ณํ์ ๊ฐ๊ฒ ๋ฉ๋๋ค.
๊ทธ๊ฒ์ ์๋ฏธ๊ฐ ์์ต๋๋ค. ํ ๊ฐ์ง ์ด๋ ค์์ Babel AST๊ฐ DU๋ก ๊ตฌ์ฑ๋์ง ์์๊ธฐ ๋๋ฌธ์ ํจํด ์ผ์น๋ก ํ์ํ๊ธฐ๊ฐ ์กฐ๊ธ ๋ ์ด๋ ต๋ค๋ ๊ฒ์ ๋๋ค. #2158์ด ๋์์ด ๋ ๊น์?
@alfonsogarciacaro ๋ด๊ฐ ์๊ฐํ๋ (ํฌ๋ง) ์ค์ ๋ก ์๋ํ ์ ์๋ ๋ฐฉ์์ผ๋ก ํ์ดํ ํจ์์ ํจ์ ํํ์์ ์ฌ์์ฑ์ ๊ณ ์น ์ ์์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์์ด๋์ด๋ ๋ชจ๋ ํํ์( TransformAsExpr
)์ด ๋ช
๋ น๋ฌธ ๋ชฉ๋ก(์ฐ๊ฒฐ๋์ด ๋ง์ง๋ง ๋ช
๋ น๋ฌธ ๋ชฉ๋ก(last-statement-level)๊น์ง ์ ๋ฌ๋์ด์ผ ํจ)๋ ๋ฐํํ๋ค๋ ๊ฒ์
๋๋ค. ๋ฐํ๋ ๋ช
๋ น๋ฌธ(func-def)์ ์๋ก ๋ค์ด ์ฌ๋ ค ๋ค๋ฅธ ๋ช
๋ น๋ฌธ ์์ ๊ธฐ๋ก๋ฉ๋๋ค. ๋ฐ๋ผ์ ํ์ดํ ๋๋ ํจ์ ํํ์์ name-expression, [statement ]
๋ฅผ ๋ฆฌํดํ๋ฉฐ ์ฌ๊ธฐ์ ํ์ดํ/ํจ์ ํํ์์ a๋ก ๋ค์ ์์ฑ๋ฉ๋๋ค. ๋ช
๋ น๋ฌธ ๋ฐ ์ด๋ฆ ํํ์๊ณผ ํจ๊ป ๋ฐํ๋ฉ๋๋ค. ์ด๋ ๋ค์์ ์๋ฏธํฉ๋๋ค.
module QuickTest
let fn args cont =
cont args
let b = fn 10 (fun a ->
printfn "test"
a + 1
)
๋ค์ JS๋ฅผ ์์ฑํฉ๋๋ค.
import { printf, toConsole } from "./.fable/fable-library.3.1.1/String.js";
export function fn(args, cont) {
return cont(args);
}
export const b = fn(10, (a) => {
toConsole(printf("test"));
return (a + 1) | 0;
});
๊ทธ๋ฌ๋ฉด ๋ค์ Python์ด ์์ฑ๋ฉ๋๋ค.
from expression.fable.string import (printf, toConsole)
def fn(args, cont):
return cont(args)
def lifted_5094(a):
toConsole(printf("test"))
return (a + 1) | 0
b = fn(10, lifted_5094)
ํด๋ก์ ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์์ ์ ์๋ค๊ณ ์๊ฐํ์ง๋ง ๋๋ถ๋ถ์ ๊ฒฝ์ฐ(๋ชจ๋ ?) ํด๋ก์ ๋ ํด์ ๋ฉ๋๋ค. ์:
module QuickTest
let add(a, b, cont) =
cont(a + b)
let square(x, cont) =
cont(x * x)
let sqrt(x, cont) =
cont(sqrt(x))
let pythagoras(a, b, cont) =
square(a, (fun aa ->
printfn "1"
square(b, (fun bb ->
printfn "2"
add(aa, bb, (fun aabb ->
printfn "3"
sqrt(aabb, (fun result ->
cont(result)
))
))
))
))
๋ค์๊ณผ ๊ฐ์ด ๋ค์ ์์ฑ๋ฉ๋๋ค.
from expression.fable.string import (printf, toConsole)
def add(a, b, cont):
return cont(a + b)
def square(x, cont):
return cont(x * x)
def sqrt(x, cont):
return cont(math.sqrt(x))
def pythagoras(a, b, cont):
def lifted_1569(aa):
toConsole(printf("1"))
def lifted_790(bb):
toConsole(printf("2"))
def lifted_6359(aabb):
toConsole(printf("3"))
return sqrt(aabb, lambda result: cont(result))
return add(aa, bb, lifted_6359)
return square(b, lifted_790)
return square(a, lifted_1569)
์ด์จ๋ ์์์ด ์ข๋ค ๐
๋๋ PHP์ ๋ํด ๋งค์ฐ ๋์ผํ ์์ ์ ์ํ ํ์ผ๋ฉฐ(BGA ์์ ์ค์ ) ์ฌ๊ธฐ์ ๋ ธ๋ ฅ์ ๊ฒฐํฉํ ์ ์์ต๋๊น?
@ncave Jupyter ๋ ธํธ๋ถ๊ณผ ๊ฐ์ ๋ํ์ ์ฌ์ฉ์ Fable์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํ ํ์ด ์์ต๋๊น? ๋ฌธ์ ๋ Jupyter๊ฐ ์ฝ๋ ์กฐ๊ฐ(์ )์ ์ ๊ณตํ๊ณ ์ปค๋์ด ์ด์ ๋ช ๋ น๋ฌธ์ ๊ธฐ์กด ๋ก์ปฌ ์ ์ธ๊ณผ ํจ๊ป ์ด ์กฐ๊ฐ์ ์ปดํ์ผํด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค.
Fable์ ์ด์ ์ต์ ์ด ์๋์ง๋ง ์ด์ ๋ช ๋ น๋ฌธ/์ ์ธ(let, type, open)์ ์ฌ์ ์ ์์๋๋ก ์ ์งํ๊ณ ๋ง์ง๋ง ์ฝ๋ ์กฐ๊ฐ๊ณผ ํจ๊ป ์์๋๋ก ์ฌ์ฉํ์ฌ ์ ํจํ F# ํ๋ก๊ทธ๋จ์ ๋ง๋๋ PoC๋ฅผ ๋ง๋ค์์ต๋๋ค. ์ฝ๋ ์กฐ๊ฐ์ ๋ชจ๋ ์ ์ธ์ ์คํ ์ ์ ์ฌ์ ์์ ์ ๊ฑฐ๋๊ณ ์คํ ํ์ ์ถ๊ฐ๋ฉ๋๋ค. ์ด๊ฒ์ ์๋ํ๋ ๊ฒ ๊ฐ์ง๋ง ๋ ๋์ ๋ฐฉ๋ฒ์ด ์๋์ง ๊ถ๊ธํฉ๋๋ค.
์ถ์ฒ: https://github.com/dbrattli/Fable.Jupyter/blob/main/fable/kernel.py#L85
๊ทธ๋ฐ ๋ค์ Fable.fs๊ฐ ์ ๋ฐ์ดํธ๋ ๋๋ง๋ค ๋ค์ ์ปดํ์ผํ๋ Fable cli๊ฐ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์คํ๋๊ณ ์์ต๋๋ค.
dotnet watch -p src/Fable.Cli run -- watch --cwd /Users/dbrattli/Developer/GitHub/Fable.Jupyter --exclude Fable.Core --forcePkgs --python
@dbattli ์กฐ๊ฐ์ด ์์ ๊ฒฝ์ฐ ํฉ๋ฆฌ์ ์ผ๋ก
์ฐธ๊ณ ๋ก, ๋ ๋ง์ ์ ์ด๊ฐ ํ์ํ ๊ฒฝ์ฐ CLI๋ฟ๋ง ์๋๋ผ Fable์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ก ์ฌ์ฉํ ์๋ ์์ต๋๋ค( fable-standalone
๋ฐ ์ฌ์ฉ ์ ์ฐธ์กฐ ).
1) ์ ๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ฌธ์ ๋ Fable AST์ ์ค๋ก์ฐ/๋ ์ด์ฆ๊ฐ ์๋ค๋ ๊ฒ์ ๋๋ค. ๋ฐ๋ผ์ ์ด๊ฒ์ ๋ด๊ฐ ๊ตฌ๋ฌธ ๋ถ์ํ๊ธฐ ์ด๋ ค์ด Emit ํํ์์ผ๋ก ๋ง๋ค์ด์ง๋๋ค. ๋๋ ์ ์ด๋ Babel์ ThrowStatement๊ฐ ์๋ ๊ฒฝ์ฐ์๋ ๋ถํ์ํด ๋ณด์ ๋๋ค. ์ฌ์ฉํ์ง ์๋ ์ด์ ๊ฐ ์์ต๋๊น? ์๋๋ฉด ๊ณ ์ณ์ผ ํฉ๋๊น? @alfonsogarciacaro
let divide1 x y =
try
Some (x / y)
with
| :? System.DivideByZeroException -> printfn "Division by zero!"; None
let result1 = divide1 100 0
์์ฑ:
export function divide1(x, y) {
try {
return ~(~(x / y));
}
catch (matchValue) {
throw matchValue;
}
}
export const result1 = divide1(100, 0);
์ฌ๊ธฐ์ throw matchValue
๋ EmitExpression
์
๋๋ค.
2) ThisExpr
๋ฅผ Fable AST์ ์ถ๊ฐํด์ผ this
๊ฐ thisKeyword๋ก ์ฌ์ฉ๋๊ณ ์๋์ง ํ์ธํ ์ ์์ต๋๋ค. ํ์ค ํจ๊ป ํ ์ ์์ต๋๋ค Fable.IdentExpr
์ค์ ๋์ด this
๊ฐ์ด - ํค์๋์ ๊ฒฝ์ฐ ๋๋ํ์ง ์ด๋ฌํ ์๊ตฌ๊ฐ ๋ฒ์ญ ๋ ๋๋ฌธ์ self
ํ์ด์ฌํ๋ค.
https://github.com/fable-compiler/Fable/blob/nagareyama/src/Fable.Transforms/Fable2Babel.fs#L792
์๊ธฐ๋ค์. throw๋ ์ค์ ๋ก Fable 2 AST์ ์์์ง๋ง Fable 3์์๋ ํ ๊ณณ์์๋ง ์ฌ์ฉ๋์๊ธฐ ๋๋ฌธ์ AST๋ฅผ ๋จ์ํํ๊ธฐ ์ํด ์ ๊ฑฐํ์ง๋ง ๋ค์ ์ถ๊ฐํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค.
"์ด๊ฒ"์ ๋ํด์๋ ๊น๋ค๋กญ์ต๋๋ค. F# AST์์๋ ์์ฑ์๋ ๋ฉ์๋์์ ๋ค๋ฅด๊ฒ ํํ๋๊ธฐ ๋๋ฌธ์ ๋ค์ ํ์ธํด์ผ ํฉ๋๋ค(์ฝ๋ ์ ์ฒด์ ์ด์ ๋ํ ์ฃผ์์ด ํฉ์ด์ ธ ์์). Fable AST์๋ ์๋ณ์์ ๋ํ IsThisArgument ์์ฑ์ด ์์ง๋ง ์ด๊ฒ์ด ๋ถ๋ฆฌ๋ ๊ตฌ์ฑ์์ ์ฒซ ๋ฒ์งธ ์ธ์์๋ง ํด๋นํ๋์ง ๋๋ "์ค์ this"์๋ ์๋ํ๋์ง ํ์ธํ๊ฒ ์ต๋๋ค.
@alfonsogarciacaro "internal" ๋ "user" ์ปดํ์ผ๋ ์ฝ๋๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ฝ๊ฐ์ ๋์์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด Exception have eg .message
ํ์ง๋ง ์ด๊ฒ์ ์ด๋ป๊ฒ ๋ฒ์ญํด์ผ ํฉ๋๊น? ์ฌ์ฉ์๊ฐ ์ปดํ์ผํ ์ฝ๋์ .message
์๊ณ ํญ์ ๋์ Test__Message_229D3F39(x, e)
๋ก ๋๋์ ๊ฐ์ญํ์ง ์์ ๊ฒ์ด๋ผ๊ณ ํ์ ํ ์ ์์ต๋๊น? ์๋๋ฉด JsException
๊ฐ์ฒด ๋ด์์ catch'๋ ์์ธ๋ฅผ ๋ํํ๊ณ ํ์คํ๊ฒ ํ๊ธฐ ์ํด .message
์์ฑ์ ์ถ๊ฐํด์ผ ํฉ๋๊น? Fable์ F#์์ Babel๋ก ์ด ์์
์ ์ด๋ป๊ฒ ์ํํฉ๋๊น? ์ ํ์ ์ถ์ ํฉ๋๊น, ์๋๋ฉด?
์๋ฅผ ๋ค๋ฉด : ์ด๋ป๊ฒ ex.Message.StartsWith
F์ #์ด ๋ ex.message.indexOf
JS์์? ์ด๊ฒ์ Python์์ str(ex).index
๋ก ๋ณํํด์ผ ํฉ๋๋ค(๋๋ ๊ฐ์ฒด๋ฅผ ๋ํ).
์ค์ ๋ก F# ์์ธ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค(์: int * int์ ์์ธ Foo). Fable 3 ๋ฆด๋ฆฌ์ค ์ ์ ์์ ํ์ง ์์์ต๋๋ค ๐ System.Exception์ JS ์ค๋ฅ๋ก ๋ณํ๋๋ฏ๋ก .message ํ๋๊ฐ ์์ต๋๋ค. ๊ทธ๋ฌ๋ F# ์์ธ๋ ์ฑ๋ฅ์์ ์ด์ ๋ก JS ์ค๋ฅ์์ ํ์๋์ง ์์ต๋๋ค(์ง๊ธ์ .Message์ ์ก์ธ์คํ๋ ค๋ ์๋๊ฐ ์คํจํ๋ค๊ณ ์๊ฐํฉ๋๋ค). ์ด๋๊ฐ์ ์ด๊ฒ์ ๋ํ ํ ๋ก ์ด ์์ต๋๋ค. ๊ทํ์ ๊ฒฝ์ฐ์ ์ผ๋ฐ์ ์ธ ์์ธ์ ๋ํด ์ง๊ธ์ Fable์ด .message ๋ฐ .stack ์์ฑ์ ์ก์ธ์คํ๋ค๊ณ ๊ฐ์ ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์ฐ๋ฆฌ๋ Fable์์ ์ธ์ด ์ ํ์ ์ด๋ป๊ฒ ์ํฉ๋๊น? ์ค๋ ์ฐ๋ฆฌ๋ --typescript
์ฌ์ฉํ์ฌ TypeScript๋ฅผ ์ ํํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ --python
์ฌ์ฉํ์ฌ Python์ ์ ํํ ์ ์์ต๋๋ค. ํ์ง๋ง .js
์์ฑ์ ์ค์งํด์ผ ํฉ๋๊น? ์๋ฅผ ๋ค์ด Emit์ด ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ ์์ฑ๋ JS๊ฐ ์ ํจํ์ง ์์ ์ ์์ผ๋ฏ๋ก ์๋ง๋ ๊ทธ๋์ผ ํ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ ๋๋๋ก ์ฐ๋ฆฌ๋ JS๋ฅผ ๋ณด๊ณ ์ถ์ดํฉ๋๋ค. --javascript
๋ํ ์ต์
์ด ์์ด์ผ ํฉ๋๊น, ์๋๋ฉด ์ฌ์ฉ์๊ฐ JavaScript๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด --python
์์ด ์คํํ๋๋ก ์๊ตฌํด์ผ ํฉ๋๊น? @alfonsogarciacaro
@dbrattli --typescript
๋ .ts
ํ์ผ๋ง ์์ฑํ๋ฏ๋ก ์ํ๋ ๊ฒฝ์ฐ --python
๋ .py
ํ์ผ๋ง ์์ฑํ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ๊ธฐ์ ์ ์ผ๋ก ๋ชจ๋ ์ํธ ๋ฐฐํ์ ์ด๋ฏ๋ก ๋์ JavaScript/TypeScript/Python
๊ฐ์ ๊ฐ์ง ์๋ก์ด --language
์ค์์น๋ฅผ ๋์
ํด์ผ ํฉ๋๊น?
@ncave ์, JavaScript
๊ฐ ๊ธฐ๋ณธ๊ฐ์ด ๋ ์ ์๋ [-lang|--language {"JavaScript"|"TypeScript"|"Python"}]
์ ๊ฐ์ ๊ฒ์ด ์ข์ ์๊ฐ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ปดํ์ผ๋ฌ์ ๋ํ ์ธ์ด ์์ฑ์ ์ด๋ฏธ ์ถ๊ฐํ๊ธฐ ์์ํ์ผ๋ฏ๋ก ๋ช
๋ น์ค ์ต์
๋ ์์ ํ ์ ์์ต๋๊น? https://github.com/fable-compiler/Fable/pull/2345/files#diff -9cb94477ca17c7556e6f79d71ed20b71740376f7f3b00ee0ac3fdd7e519ac577R12
์ผ๋ถ ์ํ์
๋๋ค. Python ์ง์์ด ํฅ์๋๊ณ ์์ต๋๋ค. ์ด์ ๋ง์ ์ธ์ด ๊ธฐ๋ฅ์ด ์ ๊ณต๋ฉ๋๋ค. ๋จ์ ํฐ ๊ณผ์ ๋ ์ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ํ๋ ๊ฒ์
๋๋ค. ์ด๊ฒ์ ๋ ์ฝ๊ฒ ํ๊ธฐ ์ํด Python์ฉ ์ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ repo๋ก ์ด๋๋์์ผ๋ฏ๋ก ๋ง์ ์ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ .fs
ํ์ผ์ Python์ผ๋ก ๋ณํํ๊ณ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๋ค ์ค ๋ค์๋ ๊ฐ๋ก์ฑ์ "์๋์ผ๋ก" ์ฒ๋ฆฌํด์ผ ํ๋ JS ๋ฐฉ์ถ ์ฝ๋๋ฅผ ํฌํจํฉ๋๋ค. Python์ ๋ํ ํ
์คํธ ์ค์ (pytest ๊ธฐ๋ฐ)์ ํ์ฌ 43๊ฐ์ ํ
์คํธ๋ฅผ ํต๊ณผํ ์ํ์ด๋ฏ๋ก ์๋ก์ด ๊ธฐ๋ฅ์ ๊ฐ๋ฐํ๊ณ ์ถ๊ฐํ๊ธฐ๊ฐ ํจ์ฌ ์ฌ์์ก์ต๋๋ค(๊ทธ๋ฆฌ๊ณ ์๋ ์ค์ธ ๊ธฐ๋ฅ์ ๋ณด์ฌ์ค).
Python์ฉ ์ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ตฌ์ถ: dotnet fsi build.fsx library-py
Python ํ
์คํธ ์คํ: dotnet fsi build.fsx test-py
@dbattli
์ด์์ ์ผ๋ก๋ fable-library
๋ฅผ F#์ผ๋ก ๋ ๋ง์ด ๋ณํํด์ผ ํฉ๋๋ค. List
๋ฐ Seq
๋ ์ด๋ฏธ ์๊ณ Array
๋ ์์์ ๊ธฐ๋ณธ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉฐ ์๋ง๋ ๋ถ๋ฆฌ๋ ์ ์์ต๋๋ค.
์ฝ๊ฐ ๋ค๋ฅธ ์ฃผ์ ์ ๋ํด Fable AST์์ ์ง์ ์ฌ์ฉํ๋ ๋์ Babel AST์์ ์๋ก์ด ์ธ์ด ์ฝ๋์ ์ ๊ตฌํํ๋ ์ฃผ์ ์ด์ ์ ๋ฌด์์ด๋ผ๊ณ ์๊ฐํ์ญ๋๊น?
@ncave Python๊ณผ JavaScript๋ ๋งค์ฐ ๊ฐ๊น๊ธฐ ๋๋ฌธ์(imo) Babel AST๋ฅผ ๋ค์ ์์ฑํ๊ธฐ๊ฐ ์๋์ ์ผ๋ก ์ฝ์ต๋๋ค. RxJS์์ RxPY๋ก ์ด์ ์ Python์ผ๋ก ์ฝ๊ฐ์ JS๋ฅผ ์ด์ํ์ต๋๋ค. ์ฐ๋ฆฌ๋ ๋ํ "์
์คํธ๋ฆผ"์ผ๋ก ๋ง๋ค์ด์ง๋ ๋ชจ๋ (๋ฒ๊ทธ-)์์ ์ ์ด์ ์ ์ป์ต๋๋ค. ์ฆ, Fable2Babel.fs
๋๋ถ๋ถ์ ์ฌ์ฌ์ฉํ๊ณ Fable2Babel.fs
์ Babel2Python.fs
๋ฅผ ๊ฒฐํฉ/์ถ์ํ๋ Fable2Python.fs
๋ฅผ ์ฌ์ฉํ์ฌ Python์ผ๋ก ์ง์ ๋ณํํ ์ ์์ต๋๋ค. ์ฌ์ค ์ค๋ ์ผ์ฐ ๊ทธ ์๊ฐ์ ํ๋ค. ๊ทธ๋ฐ ๋ค์ ํฌํฌ์ ๋ฒ๊ทธ ์์ ์ด ๋ ์์น์ ๋ชจ๋ ์ ์ฉ๋์ด์ผ ํ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค. ์ง๊ธ์ Babel AST๋ฅผ ๋ณํํด๋ ๊ด์ฐฎ๋ค๊ณ ์๊ฐํ์ง๋ง ๊ฒฐ๊ตญ์๋ Fable AST๋ฅผ ์ง์ ๋ณํํ๊ณ ์ถ์ ์๋ ์์ต๋๋ค.
๋ฉ์ง๋ค์ @dbattli! ๋ชจ๋ ์์ ์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ์ฌ์ค, ๋ด๊ฐ ์ผ๋์ ๋ ๊ฒ์ ๋๋ถ๋ถ์ Fable ์ฝ๋๋ฅผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฃ๊ณ fable(-js), fable-py(๋๋ ๋ค๋ฅธ ์ด๋ฆ)์ ๊ฐ์ ๋ค์ํ ๊ตฌํ์ ๋ ๋ฆฝ์ ์ธ dotnet ๋๊ตฌ๋ก ์ถ์ํ๋ ๊ฒ์ด์์ต๋๋ค. ๋ฆด๋ฆฌ์ค ์ฃผ๊ธฐ์์ ๋ ๋ง์ ์์ ๋ฅผ ์ป์ ์ ์์ง๋ง ๋ ์ธ์ด๋ก ์ปดํ์ผํ ์ ์๋ ๋จ์ผ dotnet ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๋ ๊ด์ฐฎ์ต๋๋ค. ํนํ ์ฒ์์๋ ๋ ๊ฐ๋จํ ์ ์์ต๋๋ค.
fable-library์ ๋ํด ๊ทธ๋ ์ต๋๋ค. ๊ฐ๋ฅํ๋ฉด ํ์ฌ .ts ํ์ผ์ ํ์ด์ฌ์ผ๋ก ๋ค์ ์์ฑํ๋ ๋์ F#์ผ๋ก ํฌํ
ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. Emit
์ฌ์ฉํ์ฌ ๋ถ๋ถ์ ๋ถ๋ฆฌํ๊ณ #if
๋ฅผ ์ฌ์ฉํ์ฌ Python์ ์ ์ฉํด์ผ ํฉ๋๋ค.
#if FABLE_COMPILER_PYTHON
[<Emit("print($0)")>]
let log(x: obj) = ()
ใ// Other native methods ...
#else
[<Emit("console.log($0)")>]
let log(x: obj) = ()
// ...
#endif
๋๋ ์๋ก์ด "๋ค๊ตญ์ด" Emit ์์ฑ์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
type EmitLangAttribute(macros: string[]) =
inherit Attribute()
[<EmitLang([|"js:console.log($0)"; "py:print($0)"|])>]
let log(x: obj) = ()
@alfonsogarciacaro ์ @ncave ์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ์ข์ ์์ด๋์ด์
๋๋ค. ์ด๋ค ํจ๊ณผ๊ฐ ์๋์ง ์์๋ณด๊ธฐ ์ํด ์๋ํด ๋ณด๊ฒ ์ต๋๋ค. Fable-library๋ฅผ F#์ผ๋ก ๋ฒ์ญํ๋ ๊ฒ์ ์ด์ ์ ์๊ณ ์์ผ๋ฏ๋ก Python ์ปดํ์ผ๋ฌ๊ฐ ๊ฑฐ๊ธฐ์์ ํ์ผ์ ์ฒ๋ฆฌํ๊ธฐ์ ์ถฉ๋ถํ๋ฉด ์ฌ๊ธฐ์์ ๋์์ ์ฃผ๋ ค๊ณ ๋
ธ๋ ฅํ ๊ฒ์
๋๋ค. #if
๋ฅผ ์ฌ์ฉํ๋ฉด ๋ง์ ๋์์ด ๋ ๊ฒ์ด๋ฉฐ, ๋ฐฉ์ถ์ ์ธ์ด๋ณ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ๋ก ์ด๋ํ์ฌ #if
ํผํ ์ ์์ ๊ฒ์
๋๋ค(Python์ ๋ํ ๋ณ๋์ .fsproj
ํ์ผ์ด ์๊ธฐ ๋๋ฌธ์).
@alfonsogarciacaro ๋์ ๋ ๊ฐ์ ๋ฐฉ์ถ ์์ฑ์ด ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น? JS์ ๊ฒฝ์ฐ Emit, Python์ ๊ฒฝ์ฐ EmitPy. ํ์ด์ฌ ํธ๋์คํ์ผ๋ฌ๋ JS ๋ฑ์ ๋ํด ๋ฐฉ์ถ์ด ๋ฐ์ํ๋ฉด ์ํ๋ฅผ ๋ณด๊ณ ํด์ผ ํฉ๋๋ค.
๋ด 2์ผํธ์ ๊ฒฝ์ฐ, ๋๋ ๋จ์ํ ๋ฐฉ์ถํ๋ ๋จ์ผ ๋ฐฉ์ถ ์์ฑ์ ๊ฐ๋ ํ์ฌ์ ๋ฎ์ ์ธ์ง ๋ถํ๋ฅผ ์ข์ํฉ๋๋ค. @dbattli ๊ฐ ์ง๊ธ ํ๊ณ ์๋ ์ผ์ ์ดํด๊ฐ ๋ฉ๋๋ค(๊ฐ fable-library
์ธ์ด ๋ฒ์ ๋ง๋ค ๋ค๋ฅธ ํ๋ก์ ํธ ํ์ผ). ๋์ค์ ํธ์ถํ ์ ์ ์๋ ์ธํฐํ์ด์ค(๋๋ ๋ชจ๋)๋ฅผ ๊ตฌํํ๋ ์์ฒด ํ์ผ์์ ๋ค๋ฅธ ์ธ์ด ๋ฐฉ์ถ์ ์ผ๋ฐ F# ๊ตฌํ๊ณผ ๋ถ๋ฆฌํ ์ ์์ต๋๋ค.
์ข์ ์๋ Array.Helpers ๋ฅผ ๊ฐ ๋์ ์ธ์ด์ ๋ํด ๊ตฌํํ ์ ์๋ ์ธํฐํ์ด์ค๋ก ๋ณํ(๋๋ ๊ทธ๋ฅ ๋ชจ๋๋ก ๋จ๊ฒจ fable-library
๋ฅผ F#์ผ๋ก ๋ ๋ง์ด ๋ง์ด๊ทธ๋ ์ด์
ํ๋ ค๋ ์ด๋ฌํ ๋
ธ๋ ฅ( --language
์ปดํ์ผ๋ฌ ์ต์
๋ ํฌํจ)์ ์ด PR๊ณผ ๋ณ๋์ PR์ ๋ค์ด๊ฐ ์ ์์ผ๋ฏ๋ก ๋ ๋น ๋ฅด๊ณ ์ฝ๊ฒ ๊ธฐ์ฌํ ์ ์์ต๋๋ค. .
์ข์ ์๊ฐ์
๋๋ค @ncave :+1: ์ฌ์ค ์ฐ๋ฆฌ๋ ๋ฉํฐํ๋ซํผ Fable ํ๋ก์ ํธ(.net ๋ฐ js)์์ ๋ค์ดํฐ๋ธ ์ฝ๋๋ฅผ ๋ถ๋ฆฌํ ๋ ์ด๋ฏธ ์ด๊ฒ์ ํ๊ณ ์์ต๋๋ค. ์ผ์ ๋จ์ํํ๊ธฐ ์ํด Fable.Library์ ์ Native.fs
ํ์ผ์ ์ถ๊ฐํ๊ณ ํ์์ ๋ฐ๋ผ ๋ค์๊ณผ ๊ฐ์ด ํ์ ๋ชจ๋์ ์ถ๊ฐํ ๊ฒ์
๋๋ค.
namespace Fable.Library.Native # or just Native
module Array = ..
module Map = ..
Emit
๋๋ Fable.Core.JS
๊ฐ์ ์ฌ์ฉํ๋ ๋ชจ๋ ํญ๋ชฉ์ ๊ทธ๊ณณ์ผ๋ก ์ด๋ํด์ผ ํฉ๋๋ค.
๋น๋๊ธฐ ์์
์์ Async.ts
๋ฐ AsyncBuilder.ts
๋ฅผ F#์ผ๋ก ์ด์ํ๋ ค๊ณ ํฉ๋๋ค. ์ฆ Async.fs
๋ฐ AsyncBuilder.fs
์์ต๋๋ค. ํ์ง๋ง ์ด์ ์ฝ๋๊ฐ ํฌํจ๋ ํ
์คํธ ํ์ผ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
async { return () }
|> Async.StartImmediate
Python(JS ์ฝ๋๋ ๋งค์ฐ ์ ์ฌํด์ผ ํจ) ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค.
startImmediate(singleton.Delay(lambda _=None: singleton.Return()))
๊ทธ๋ฌ๋ AsyncBuilder์๋ ๋ฉ์๋๊ฐ ์์ง๋ง AsyncBuilder__Delay_458C1ECD
์์ต๋๋ค. ๊ทธ๋์ AttributeError: 'AsyncBuilder' ๊ฐ์ฒด์ 'Delay' ์์ฑ์ด ์์ต๋๋ค.
class AsyncBuilder:
def __init__(self):
namedtuple("object", [])()
def AsyncBuilder__ctor():
return AsyncBuilder()
def AsyncBuilder__Delay_458C1ECD(x, generator):
def lifted_17(ctx_1):
def lifted_16(ctx):
generator(None, ctx)
protectedCont(lifted_16, ctx_1)
return lifted_17
...
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋ํ ํํธ๊ฐ ์์ต๋๊น? @ncave @alfonsogarciacaro. ๋๋ F์ # ํด๋์ค ๋ฉ์๋์ ํด๋์ค๋ฅผ ์์ฑ ํ , ๋๋ ๋ด ํ
์คํธ ํ ์์๋ ๋ฐฉ๋ฒ์ด ์ฝ๋๊ฐ ์์ฑ๋์ด ๊ทธ ์ฉ๋ ์ ์ AsyncBuilder__Delay_458C1ECD
๋์ .Delay()
?
@dbrattli ์ผ๋ฐ์ ์ผ๋ก ๋ง๊ฐ์ง์ง ์๊ธฐ๋ฅผ ์ํ๋ ๋ฉ์๋์ ๋ํ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค.
๊ด๋ จ ๋ฉ๋ชจ์์ ๋น๋๊ธฐ ์ง์์ ๋ค์ดํฐ๋ธ Python asyncio
์ ๋ฒ์ญ์ ๋ ์ ํฉํ ๊ธฐ๋ฅ ์ค ํ๋์
๋๊น?
@ncave ์๊ฒ ์ต๋๋ค. ์๋ ๋ฐฉ์์
๋๋ค ๐ ํต์ฐฐ๋ ฅ ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค. ๋น๋๋ฅผ ์ธํฐํ์ด์ค ๋ค์ ๋๊ณ ๋์์ด ๋๋์ง ํ์ธํ๋ ค๊ณ ํฉ๋๋ค(F# ๋น๋๊ฐ ์ธํฐํ์ด์ค๊ฐ ์๋๋๋ผ๋ ์ ๋๋ก ์๋ํด์ผ ํจ). async
๊ดํด์๋ ๊ธฐ๋ณธ Python asyncio( ์ฌ๊ธฐ ์ฐธ์กฐ )๋ฅผ ์ฌ์ฉํ๋ ๊ณํ์ด์์ง๋ง python cannot reuse already awaited coroutine
์ ๋ฌธ์ ๊ฐ ์์ผ๋ฏ๋ก ํจ์ ๋ค์์ ์ง์ฐ์์ผ์ผ ํฉ๋๋ค. ์ด์จ๋ ์ ๋ Python ๋ค์ดํฐ๋ธ awaitables์ task
๋๋ asyncio
๋น๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ ์์์ต๋๋ค. AsyncBuilder.ts
์ ๋จ์ํ๋ F#์ผ๋ก ์ด์ํ๋ ค๊ณ ํ๋ ์ ๋ฅผ ๋งค๋ฃ์์ผฐ์ต๋๋ค.
๋งน๊ธ๋ง์ ํผํ๊ธฐ ์ํด ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ @ncave๊ฐ ๋งํ ๋๋ก ์๋ํด์ผ ํฉ๋๋ค. ์ฐ๋ฆฌ๋ ๋ํ ๋ช ๊ฐ์ง ๋ค๋ฅธ ์ ๊ทผ ๋ฐฉ์์ ์๋ํ์ต๋๋ค.
NoOverloadSuffix
์์ฑ: Fable์ด ์ค๋ฒ๋ก๋ ์ ๋ฏธ์ฌ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค. ๋ถ๋ช
ํ ์ค๋ฒ๋ก๋๋ ์ด ๊ฒฝ์ฐ์ ์๋ํ์ง ์์ ๊ฒ์
๋๋ค.๊ทธ๋ฐ ๋ค์ Naming.buildNameWithoutSanitation
์ฌ์ฉํ์ฌ ๋ฉ์๋๋ฅผ ์ฐธ์กฐํ ์ ์์ต๋๋ค.
src/fable-library/System.Text.fs
:์ด ๊ฒฝ์ฐ replacedModules
์ฌ์ ์ ํด๋์ค๋ฅผ ์ถ๊ฐํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
๋ฐ๋ผ์ ๋ถํํ๋ Replacements
์์ F#์ผ๋ก ์์ฑ๋ ์ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฝ๋์ ์ฐ๊ฒฐํ๋ ์ผ๊ด๋ ์ ๊ทผ ๋ฐฉ์์ด ์์ง ์์ต๋๋ค. ์ด์ฉ๋ฉด ์ฐ๋ฆฌ๋ ์ง๊ธ ํ๋์ ๋์ํ๊ธฐ ์ํด์ด ๊ธฐํ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๋งค์ฐ ํฅ๋ฏธ๋ก์ด ํต์ฐฐ๋ ฅ @ncave ๋ฐ @alfonsogarciacaro์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ์ธํฐํ์ด์ค์์ ๋๋ ๋ ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ์ต๋๋ค. Python์์ unit
๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์
๋๊น? ๋ด ์ธํฐํ์ด์ค๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
type IAsyncBuilder =
abstract member Bind<'T, 'U> : IAsync<'T> * ('T -> IAsync<'U>) -> IAsync<'U>
abstract member Combine<'T> : IAsync<unit> * IAsync<'T> -> IAsync<'T>
abstract member Delay<'T> : (unit -> IAsync<'T>) -> IAsync<'T>
abstract member Return<'T> : value: 'T -> IAsync<'T>
...
๋ฌธ์ ๋ Return
๊ฐ ๋ค์์ ์์ฑํ๋ค๋ ๊ฒ์
๋๋ค.
class AsyncBuilder:
def Return(self, value):
return protectedReturn(value)
....
์ด๊ฒ์ ์ข์ ๋ณด์ด๊ณ ์๋ง๋ JS์ ์ข์ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ ํ์ด์ฌ์์๋ ํจ์๊ฐ ์ธ์๋ฅผ ์ทจํ๋ ๊ฒฝ์ฐ ์ธ์๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค. ๋ฐ๋ผ์ 'T
๊ฐ unit
๋ 'T
x.Return()
๋ฅผ ํธ์ถํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ๋ด ์ฒซ ๋ฒ์งธ ๋ฐ์์ ๊ณผ๋ถํ๋ฅผ ๋ง๋๋ ๊ฒ์ด ์์ต๋๋ค.
abstract member Return : unit -> IAsync<unit>
๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ๋๋ฆ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๋ด ํ์ฌ ์๋ฃจ์ (์ถํ ๋ชจ์):
abstract member Return<'T> : [<ParamArray>] value: 'T [] -> IAsync<'T>
...
member this.Return<'T>([<ParamArray>] values: 'T []) : IAsync<'T> =
if Array.isEmpty values then
protectedReturn (unbox null)
else
protectedReturn values.[0]
๊ทธ๋ฌ๋ ์ด๋ฅผ ์ํด์๋ ๋ชจ๋ ์ผ๋ฐ ๋จ์ผ ์ธ์ ํจ์์ ๋ํ ์ฌ์ฉ์ ์ ์ ์ฒ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค. ์๋ง๋ ๋ชจ๋ ๋จ์ผ ์ธ์ ํจ์๊ฐ null(Python์ ๊ฒฝ์ฐ ์์)์ ์ ๋ ฅ์ผ๋ก ๋ฐ์๋ค์ด๋๋ก ํด์ผ ํฉ๋๋ค. ์:
class AsyncBuilder:
def Return(self, value=None):
return protectedReturn(value)
....
์ด ๋ฌธ์ ๋ฅผ ์ฒ๋ฆฌํ๋ ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ์ ๋ฌด์์ ๋๊น?
IIRC, unit -> X
์๋ช
์ด ์๋ ๋ฉ์๋์ ๊ฒฝ์ฐ ํธ์ถ์๋ ์ธ์๊ฐ ์์ง๋ง(F# AST์์์ ๊ฐ์ด) ๋๋ค ๋๋ ์ด ๊ฒฝ์ฐ unit
ํธ์ถ/์์ฉ ํ๋ก๊ทธ๋จ์ผ๋ก ์ฑ์์ง ์ผ๋ฐ ์ธ์์๋ unit
Fable AST์ transformCallArgs
๋์ฐ๋ฏธ์์ ์ ๊ฑฐ๋ฉ๋๋ค. ๋์ ์ธ์ด๊ฐ ํ์ด์ฌ์ผ ๋ ์กฐ๊ฑด์ ์ถ๊ฐํ๊ณ ๋จ์ ์ธ์๋ฅผ ๊ทธ๋๋ก ๋ ์ ์์ต๋๋ค.
์๋
ํ์ธ์ @ncave , @alfonsogarciacaro , ์ ๋ Python์์ [<Inject>]
๋งค๊ฐ๋ณ์๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ์ผ๋ถ ์
๋ ฅ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๊ฒ์ Php @thinkbeforecoding์์ ์ด๋ป๊ฒ ์ํ๋ฉ๋๊น? ์๋ฅผ ๋ค์ด ( Array.fs
) ๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ:
let map (f: 'T -> 'U) (source: 'T[]) ([<Inject>] cons: Cons<'U>): 'U[] =
let len = source.Length
let target = allocateArrayFromCons cons len
for i = 0 to (len - 1) do
target.[i] <- f source.[i]
target
๋ด ์ฝ๋๋ cons
๋งค๊ฐ๋ณ์๋ฅผ ์์ฑํ์ง ์์ผ๋ฉฐ Python์ ํ์ํฉ๋๋ค.
map(fn ar)
JS์ ๊ฒฝ์ฐ ์ ํ ์ฌํญ์ ๋๊น? ์ฝ๋์์ ์์ฑ์ ๊ฐ์งํ๊ณ ์ ํ์ ์ผ๋ก ๋ง๋ค๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํฉ๋๊น? ์
def map(f, source, cons=None):
...
PHP๋ ๋ํ ์ ํ์ ๋งค๊ฐ๋ณ์์ ๋ํด ๋ช ์์ ์ ๋๋ค. ์ธ์ ๋ชจ๋ธ์ IsOptional ํ๋๊ทธ๋ฅผ ์ถ๊ฐํด์ผ ํ์ต๋๋ค.
Fable์์ Inject
์์ฑ์ ๋ ๊ฐ์ง ์ฉ๋๋ก ์ฌ์ฉ๋ฉ๋๋ค. ํ๋๋ ์ฃผ๋ก ์คํ์ ์ด๋ฉฐ(์ด๋ป๊ฒ๋ ์ ํ ํด๋์ค๋ฅผ ์๋ฎฌ๋ ์ดํธํ๊ณ ์ผ๋ฐ ์ ํ ์ ๋ณด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํจ์๋ฅผ ์ธ๋ผ์ธํด์ผ ํ๋ ๊ฒ์ ํผํ๊ธฐ ์ํด) ๋๋ฌด ์ ๊ฒฝ์ฐ์ง ์์๋ ๋ฉ๋๋ค.
๋ค๋ฅธ ์ฉ๋๋ ์ปดํ์ผ ์๊ฐ์ ํด๊ฒฐ๋ ์ธ์์ ์ํด ์ ๋ฌ๋ ์ถ๊ฐ ์ ๋ณด๊ฐ ํ์ํ fable-library ๋ฉ์๋์ ๋ด๋ถ์ ๋๋ค.
๊ทธ๋ฌ๋ ์ด๋ฌํ ํจ์๋ ์ง์ ํธ์ถ๋์ง ์์ผ๋ฏ๋ก Fable์ Inject
์์ฑ์ "๋ณผ ์ ์์ต๋๋ค". ์ด๋ฌํ ์ด์ ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ด๋ค ํจ์์ ์ฝ์
์ด ํ์ํ์ง ์๋ ค์ฃผ๋ ReplacementInject.fs ํ์ผ ์ ์ฌ์ฉํฉ๋๋ค. ์ฌ์ฉ ๋ฐฉ๋ฒ ๋ณด๊ธฐ: https://github.com/fable-compiler/Fable/blob/522f6aad211102271538798aeb90f4aed1f77dd6/src/Fable.Transforms/Replacements.fs#L988-L1019
์ด ํ์ผ์ Fable.Library์ ์ด๋ค ํจ์๊ฐ Inject
์ฅ์๋ ๋ง์ง๋ง ์ธ์๋ฅผ ๊ฐ์ง๊ณ ์๋์ง ๊ฐ์งํ๋ ์ด ์คํฌ๋ฆฝํธ๋ก ์ฒ์์ ์๋์ผ๋ก ์์ฑ๋์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ ์์ ์์ ์ฐ๋ฆฌ๋ ์
๋ฐ์ดํธ๋ฅผ ์ค๋จํ๊ณ IIRC๊ฐ ReplacementInjects์ ๋ํ ๋ง์ง๋ง ์
๋ฐ์ดํธ๋ฅผ ์ค๋จํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ํ์ผ์ ์๋์ผ๋ก ์ํํ์ต๋๋ค.
๊ทธ๊ฒ์ ์๋ฉด IsOptional ์ ๋ณด๋ฅผ ์ ๊ฑฐ ํ ์ ์์ต๋๋ค ... ํ์ธํ๊ฒ ์ต๋๋ค.
@alfonsogarciacaro ๋ค์๊ณผ ๊ฐ์ ์ฝ๋์ ๋ํด injectArg
์ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
type Id = Id of string
let inline replaceById< ^t when ^t : (member Id : Id)> (newItem : ^t) (ar: ^t[]) =
Array.map (fun (x: ^t) -> if (^t : (member Id : Id) newItem) = (^t : (member Id : Id) x) then newItem else x) ar
let ar = [| {|Id=Id"foo"; Name="Sarah"|}; {|Id=Id"bar"; Name="James"|} |]
replaceById {|Id=Id"ja"; Name="Voll"|} ar |> Seq.head |> fun x -> equal "Sarah" x.Name
replaceById {|Id=Id"foo"; Name="Anna"|} ar |> Seq.head |> fun x -> equal "Anna" x.Name
์ฌ๊ธฐ์ Array.map
๋ ์์ฑ์๋ฅผ ์ฃผ์
ํ์ง ์์ต๋๋ค. ์ฝ๋๋ ์ฃผ์
๋ ์ธ์ ์์ด JS๋ก ๋ณํ๋ฉ๋๋ค.
return map((x) => (equals(newItem.Id, x.Id) ? newItem : x), ar);
๋ฒ๊ทธ์ธ๊ฐ์? ์ด ์ฝ๋๋ JS(์ด์ด ์ข์ ๊ฑธ๊น์?)์์๋ ์๋ํ์ง๋ง Python์์๋ ์๋ํ์ง ์์ต๋๋ค.
์, ์ฃ์กํฉ๋๋ค! ์์ ํ ์์ด๋ฒ๋ ธ์ง๋ง "ํ์ค" JS ๋ฐฐ์ด์ ๋ํด ๋ฐฐ์ด ์์ฑ์๊ฐ ์ฃผ์ ๋์ง ์์ "์ต์ ํ"๊ฐ ์์ต๋๋ค. https://github.com/fable-compiler/Fable/blob/4ecab5549ab6fcaf317ab9484143420671ded43b/src/Fable.Transforms/ ๊ต์ฒด.fs#L1005 -L1009
๊ทธ๋ฐ ๋ค์ ์๋ฌด ๊ฒ๋ ์ ๋ฌ๋์ง ์์ผ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ญ Array
์
๋๋ค. https://github.com/fable-compiler/Fable/blob/4ecab5549ab6fcaf317ab9484143420671ded43b/src/fable-library/Array.fs#L25 -L28
๋ด๊ฐ ์ ์ด๋ ๊ฒ ํ๋์ง๋ ํ์คํ์ง ์์ง๋ง ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ๋ฅผ ์ํด ๋ฒ๋ค๋ก ๋ช ๋ฐ์ดํธ๋ฅผ ์ ์ฝํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค. ๋์์ด ๋๋ค๋ฉด next
๋ถ๊ธฐ์ ๋ํ ์ด ์ต์ ํ๋ฅผ ์ ๊ฑฐํ ์ ์์ต๋๋ค.
์์์ด ๊ณ ๋ง์. ์ด ์์ ์ ์ํํ ์ ์๋์ง ํ์ธํ๋ ค๊ณ ํฉ๋๋ค. ์ด ๊ธฐ๋ฅ์ ๋ ํ์๋ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. Python์ด ์ง์ํ์ง ์๋๋ก ์ธ ๋ฒ์งธ ์ธ์์ ๋ํด ๋น(null) ๊ฐ์ ์์ฑํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. ์ฆ:
| Types.arrayCons ->
match genArg with
| Number(numberKind,_) when com.Options.TypedArrays ->
args @ [getTypedArrayName com numberKind |> makeIdentExpr]
| _ -> args @ [ Expr.Value(ValueKind.Null genArg, None) ]
JS์ ๊ฒฝ์ฐ ๋ค์์ ์์ฑํฉ๋๋ค.
map((x_3) => (equals(newItem_1.Id, x_3.Id) ? newItem_1 : x_3), ar, null))).Name);
๊ทธ๋ฆฌ๊ณ ํ์ด์ฌ์ ๊ฒฝ์ฐ:
def lifted_53(x_2):
return newItem_1 if (equals(newItem_1["Id"], x_2["Id"])) else (x_2)
return map(lifted_53, ar, None)
๊ทธ๋ฐ ๊ฒ์ด ์์ฉ ๊ฐ๋ฅํ ์์ ์ฌํญ์ด ๋ ๊น์?
์๋ํด์ผ ํฉ๋๋ค. ๋์ None
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ํ ์์ ์์ ์ฐ๋ฆฌ๋ Fable2Babel์ ๋ง์ง๋ง ์์น์์ None
args๋ฅผ ์ ๊ฑฐํ์ต๋๋ค. ์ง๊ธ FSharp2Fable์์ ๊ทธ๋ ๊ฒ ํ๊ณ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ํ์ง๋ง ์ฌ๊ธฐ์ ์ถ๊ฐ ๊ฒ์ฌ๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค: https://github.com/fable-compiler/ ์ฐํ/blob/c54668b42b46c0538374b6bb2e283af41a6e5762/src/Fable.Transforms/Fable2Babel.fs#L1082 -L1095
BTW, ์ฃ์กํฉ๋๋ค ์ด PR์ ์์ธํ ํ์ธํ์ง ๋ชปํ์ต๋๋ค ๐
ํ์ง๋ง ํ
์คํธ๋ฅผ ์๋ฐํ์ง ์๋๋ค๋ฉด PHP์์ ํ๋ ๊ฒ์ฒ๋ผ ๊ณง POC๋ก ๋ณํฉํ ์ ์์ต๋๋ค. ์ด๊ฒ์ Fable๋ก ์ฌ๋ฌ ์ธ์ด๋ฅผ ๋์์ผ๋ก ํ๋ ๊ฒ์ ๋ ์ฝ๊ฒ ํ๊ธฐ ์ํด ์ฝ๊ฐ์ ๋ฆฌํฉํ ๋ง์ ์ํํ ๊ณํ(์๊ฐ ํ์ฉ) ๋๋ฌธ์ด๋ฉฐ, Python์ด ์ด๋ฏธ next
๋ถ๊ธฐ์ ์๋ค๋ฉด ๋ ์ฌ์ธ ๊ฒ์
๋๋ค. ๋ํ ๋๋ฌด ๋ง์ ๋ถ๊ธฐ ๋ถ๊ธฐ(main, next, python)๋ฅผ ๋๊ธฐํ ์ํ๋ก ์ ์งํ์ง ์์๋ ๋ฉ๋๋ค.
์ข์ @alfonsogarciacaro , null ๋์ None์ ์์ฑํ ์ ์๋์ง ํ์ธํ๊ฒ ์ต๋๋ค. ๊ณง ๋ณํฉํ ์ ์์ต๋๋ค. ์ฌ์ ํ ๊ธฐ์กด Python ํ
์คํธ ์ค ์ผ๋ถ๋ฅผ ๊นจ๋จ๋ฆฌ๊ณ ์์ง๋ง ์ด์ ๋ช ๊ฐ์ง๋ง ๋จ์๊ณ ์ผ์ฃผ์ผ ์ ๋ ์ด๋ด์ ์์ ํด์ผ ํฉ๋๋ค. ๋ํ ํ์ํ ๋ฐฉ์ถ๋ก Fable.Core.PY.fs
๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค. Babel2Python -> Fable2Python์ ์ฌ์์ฑ์ ์์๋ณด๋ค ์ด๋ ค์ ์ง๋ง ๋ง์นจ๋ด ๋ค์ ์ ์ ๊ถค๋์ ์ค๋ฅด๊ธฐ ์ํด ๊ฐ๊น์์ง๊ณ ์์ต๋๋ค. PR์ ์กฐ๊ธ ์ ๋ฆฌํ๊ณ ๋ณํฉํ ์ค๋น๋ฅผ ํ๋๋ก ํ๊ฒ ์ต๋๋ค.
@alfonsogarciacaro ํ๋๋ฅผ ์ ์ธํ ๋ชจ๋ ํ
์คํธ๋ฅผ ์์ ํ์ต๋๋ค. ๊ทธ๊ฒ์ ๊ทธ๋ฌ๋ ๋๋ ๋ฐ๋ฒจ๋กํ๋ค ๋๊ฐ์ ๋ฌธ์ ์ ๊ด๋ จ์ด ๐ฑ ๋ด๊ฐ ์๊ณ ์๋ ๋ฐฉ๋ฒ์ด ํ์ Fable.Get
์จ ์ฌ์ฉ๋๋ AnonymousRecord
๊ทธ๋ค์ด ํ์ด์ฌ ๋์
๋๋ฆฌ๋ก ๋ณํํ๊ธฐ ๋๋ฌธ์ ์ ํ, ๋ด๊ฐ ์ฌ์ฉ ์ฒจ์ ํ์ ์ฆ []
์ก์ธ์ค๊ฐ ์๋๋ผ .dotted
์
๋๋ค. ๋ฌธ์ ๋ ์ผ์ชฝ์ด ๋ฌด์์ด๋ ๋ ์ ์๋ค๋ ๊ฒ, ๊ฐ์ฒด, ํจ์ ํธ์ถ ... ๊ทธ๋์ ์๊ธฐ ์ด๋ ต์ต๋๋ค. ๋ ๋์ ๋ฐฉ๋ฒ์ด ์์ต๋๊น? ์ต๋ช
๊ธฐ๋ก์ ์ํด ๋ ๋ค๋ฅธ GetKind
๊ฐ ์์ด์ผ ํฉ๋๊น, ์๋๋ฉด ์ด๊ฒ์ ํ๋ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ๋ฌด์์
๋๊น?
FSharp2Fable์์ ์ด๊ฒ์ ๋ด ๋๋ค. FieldGet์ด AnonRecord์ ์ํด ์์ฑ๋์๋ค๋ ๊ฒ์ ๋์ค์ ์ด๋ป๊ฒ ์ ์ ์์ต๋๊น?
// Getters and Setters
| FSharpExprPatterns.AnonRecordGet(callee, calleeType, fieldIndex) ->
let r = makeRangeFrom fsExpr
let! callee = transformExpr com ctx callee
let fieldName = calleeType.AnonRecordTypeDetails.SortedFieldNames.[fieldIndex]
let typ = makeType ctx.GenericArgs fsExpr.Type
return Fable.Get(callee, Fable.FieldGet(fieldName, false), typ, r)
Discord @dbrattli ์์ ์ด์ผ๊ธฐํ ๊ฒ์ฒ๋ผ ์ต๋ช
๋ ์ฝ๋์ธ์ง ํ์ธํ๊ธฐ ์ํด ์์ ์ ์ ํ์ ํ์ธํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ณด๋ค ์ฒด๊ณ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ด ํ์ํ ๊ฒฝ์ฐ FieldGet
์ ๋ ๋ง์ ์ ๋ณด๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ํ์ง๋ง ์ด ์์ ์์ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ ์ต์ํํ๊ณ ๋ค๋ฅธ ๋ถ์ธ ํ๋์ ํผ๋์ ํผํ๊ธฐ ์ํด ๋ณ๋์ ๋ ์ฝ๋๋ฅผ ์ ์ธํด์ผ ํฉ๋๋ค(F#์ ๋ ์๊ฒฉํ ์ ๋์จ ์ผ์ด์ค ํ๋ ์ด๋ฆ btw):
type FieldGetInfo =
{ Name: string
IsMutable: bool
IsAnonymousRecord: bool }
type GetKind =
| FieldGet of info: FieldGetInfo
| ...
@alfonsogarciacaro ๊ฐ์ฌํฉ๋๋ค. ํจ๊ณผ๊ฐ ์์๋ค! ๐
๋ค์ ๋ฌธ์ :
testCase "Map.IsEmpty works" <| fun () ->
let xs = Map.empty<int, int>
xs.IsEmpty |> equal true
let ys = Map [1,1; 2,2]
ys.IsEmpty |> equal false
JS์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด ์ปดํ์ผ๋ฉ๋๋ค.
Testing_testCase("Map.isEmpty works", () => {
Testing_equal(true, isEmpty_1(ofSeq([], {
Compare: (x_1, y_1) => compare(x_1, y_1),
})));
Testing_equal(false, isEmpty_1(ofSeq([[1, 1]], {
Compare: (x_2, y_2) => comparePrimitives(x_2, y_2),
})));
})
ofSeq
๋ ๋ ๊ฐ์ ์ธ์๋ก ํธ์ถ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ofSeq
๋ ๋จ์ผ ์ธ์๋ง ์ฌ์ฉํฉ๋๋ค.
let ofSeq elements =
Map<_, _>.Create elements
export function ofSeq(elements) {
return FSharpMap_Create(elements);
}
ofSeq
๊ฐ ํธ์ถ๋ ๋ Compare
๊ฐ ์๋ ๊ฐ์ฒด ํํ์์ด ์ถ๊ฐ๋ ์ด์ ๋ ๋ฌด์์
๋๊น?
ํ , ์ด๊ฒ์ ๋ํด ์กฐ์ฌํด์ผํฉ๋๋ค. ๋ฒ๊ทธ์ฒ๋ผ ๋ณด์ด์ง๋ง ofSeq
๋ ๋น๊ต์๋ฅผ ํ์ฉํด์ผ ํฉ๋๋ค( MapTree.ofSeq
๋ฐ Set.ofSeq
์ ๊ฐ์ ์ ์ฌํ ๊ธฐ๋ฅ์ ์ํ). ์ค์ ์ด ์ฝ๊ฐ ๋ณต์กํ๋ฏ๋ก ์ด๋ค ์์ ์์ ๋๊ธฐํ๋์ง ์์์ ์ ์์ต๋๋ค. ๋์ฒด์์ ์ธ์ ์ฃผ์
์ด ํ์ํ ๋ฉ์๋๋ฅผ ๋ํ๋ด๋ ๋ฐ ์ฌ์ฉํ๋ ReplacementsInject.fs๋ผ๋ ํ์ผ์ด ์์ต๋๋ค. ์ด ํ์ผ์ ์๋์ผ๋ก ์์ฑํ๋ ์คํฌ๋ฆฝํธ๊ฐ ์ด๋๊ฐ์ ์์ง๋ง ์ฌ์ฉํ์ง ์์์ง ์ค๋๋์ด ์ต์ FCS ๋ฒ์ ์์ ์๋ํ๋์ง ํ์คํ์ง ์์ต๋๋ค. ํ์ธํ๊ฒ ์ต๋๋ค ์ง์ ๊ฐ์ฌํฉ๋๋ค!
์์ ์์ ์ ์ถ๊ฐํ์ต๋๋ค. ๊ฒํ ์ค๋น ๐ https://github.com/fable-compiler/Fable/pull/2345
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๋ฉ์ง ์ํ์ ๋๋ค @dbattli! ๐ ๐ ๐ Fable์ ์๋ ์์ด๋์ด๋ F#์ ๋ค๋ฅธ ์ธ์ด๋ก ์ฝ๊ฒ ์ปดํ์ผํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ ๊ฒ์ด์์ต๋๋ค. ์ข๋ ๋์๋ Fable์ JS๋ฅผ ์ฃผ์ ์ด์ ์ผ๋ก ๋ฐ์ ์์ผ ์๊ธฐ ๋๋ฌธ์ ์ธ์ด์ ๊ตฌ์ ๋ฐ์ง ์๊ฒ ํ๋ ค๋ฉด ์ฝ๊ฐ์ ์์ ์ด ํ์ํ์ง๋ง ์ด์ ๋ํด ๊ฐ๋ฐฉ์ ์ ๋๋ค. ๊ทํ์ ์ง๋ฌธ์ ๋ํ ๋ช ๊ฐ์ง ์๊ฒฌ:
๊ฐ๊ฑฐ๋ ๋ค๋ฅธ repo? ๊ฐ๋ฅํ ํ ๋ง์ ๊ณตํต ์ฝ๋๋ฅผ ์ ์งํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๋ค๋ฅธ ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋งค์ฐ ๋น ๋ฅด๊ฒ ๋ถ๊ธฐํ ์ ์์ง๋ง(์ธ์ฉ ์ง์์ผ๋ก ๋ถ๊ธฐ๋ฅผ ๋๊ธฐํํ๊ธฐ๊ฐ ์ด๋ฏธ ์ด๋ ต์ต๋๋ค) ๋์ ์ธ์ด์ ๋ฐ๋ผ ๋ชจ๋ ๊ณณ์์ ์กฐ๊ฑด์ด ๋ฐ์ํ์ง ์๋๋ก ์ฝ๋๋ฅผ ์ถฉ๋ถํ ๋ชจ๋ํํด์ผ ํฉ๋๋ค. ์ค๊ฐ ์๋ฃจ์ ์ Fable "Nucleus"(Core ๐๋ฅผ ์ฌ์ฉํ ์ ์์)์ ๊ฐ๋ฅํ ํ ๋ง์ ์ฝ๋๋ฅผ ์ถ์ถํ ๋ค์ ์ธ์ด ๊ตฌํ์ ๋ํด ๋ค๋ฅธ ์ ์ฅ์๋ฅผ ๊ฐ๋ ๊ฒ์ ๋๋ค.
Babel AST: ์ด๊ฒ์ ์๋ ์ฐ๋ฆฌ๊ฐ ์ฝ๋ ์ธ์๋ฅผ ์ํด Babel์ ์์กดํ๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ๋์์ต๋๋ค. ์ด์์ ์ธ ์ธ๊ณ์์๋ ์ด์ ํ๋ฆฐํฐ๊ฐ ์์ผ๋ฏ๋ก ์ ๊ฑฐํ ์ ์์ด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ Fable-to-Babel ๋จ๊ณ์์ ๋ง์ ์ผ์ด ์ผ์ด๋๊ธฐ ๋๋ฌธ์ ์ด๋ ค์ธ ๊ฒ์ ๋๋ค. ๊ฐ์ ์ด์ ๋ก ์ด ๋จ๊ณ์์ ๊ฐ๋ฅํ ํ ๋ง์ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด ๋ฐ๋์งํ ๊ฒ์ ๋๋ค. ์๋ง๋ Babel AST๋ฅผ ๋น๊ธฐ๋ฅ์ ์ธ์ด์ ๋ํด ์ข ๋ ์ผ๋ฐ์ ์ธ ๊ฒ์ผ๋ก ๋ง๋ค ์ ์์ ๊ฒ์ ๋๋ค. ๋ช ๊ฐ์ง ์:
F#์ ๋ Pythonicํ๊ฒ ๋ง๋์๊ฒ ์ต๋๊น? Fable์ ์ฌ์ฉํ๋ฉด ์ค๋ฒํค๋๋ฅผ ํผํ๊ธฐ ์ํด .NET ์๋ฏธ ์ฒด๊ณ๊ฐ ๋๋๋ก ํฌ์๋๋ ๊ท ํ์ ์ฐพ๊ธฐ ์ํด ํญ์ ๋ ธ๋ ฅํ์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ฐ๋ฆฌ๋ int์ ๋ํด ํน์ ์ ํ์ ์ฌ์ฉํ๋ ๋์ JS ๋ฒํธ๋ฅผ ์ฌ์ฉํฉ๋๋ค(long์ ๋ํด ๊ทธ๋ ๊ฒ ํ์ง๋ง). ์ด๊ฒ์ Python
int
์ ์ฉ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์๋ฅผ ๋ค์ด ์ ์ ๋๋๊ธฐ ๋๋ ๋ช ์์ ์ซ์ ๋ณํ๊ณผ ๊ฐ์ ์๊ธฐ์น ์์ ๊ฒฐ๊ณผ๋ฅผ ํผํ๊ธฐ ์ํด ํน์ ์ง์ ์์ .NET ์๋ฏธ ์ฒด๊ณ๋ฅผ ์กด์คํ๊ธฐ ์ํด ๋ง์ ๊ธฐ์ฌ๋ฅผ ํ์ต๋๋ค.์ด์จ๋ "๋ ํ์ด์ฌ์ ์ธ"์ด๋ผ๊ณ ๋งํ๋ฉด ์ฝ๋ ์คํ์ผ ๋๋ ๊ธฐ๋ณธ API๋ฅผ ์๋ฏธํฉ๋๊น? Fable์ ๋๋ถ๋ถ์ .NET BCL์ ์ง์ํ๋ ค๊ณ ํ์ง ์์ง๋ง ๊ฒฐ๊ตญ ๊ฐ๋ฐ์๊ฐ ์ต์ํ๊ฒ ์ฌ์ฉํ๋ ๊ณตํต ๊ธฐ๋ฅ/์ฐ์ฐ์๋ฅผ ์ง์ํด์ผ ํฉ๋๋ค(์ ๊ท ์ฌ์ฉ์๋ ํํ ๋ฆฌ์ผ์์ ์ฐพ์ ์ ์๊ธฐ ๋๋ฌธ์). ์ด๋ค ๊ฒฝ์ฐ์๋ ๊ธฐ๋ณธ API๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ต์ ์ ์ ๊ณตํ๋ ๊ฒ์ด ์ข์ต๋๋ค( ๊ทธ๋ฐ ์๋ฏธ์์ Fable.Extras ๋ ์ข์ ์์ง์์ ๋๋ค). ์๋ฅผ ๋ค์ด
JS.console.log
์ผ๋ฐ์ ์ผ๋กprintfn
๋ณด๋ค ๊ฐ์ฒด์ ํ์์ ์ง์ ํ์ง๋ง ๊ฐ๋ฐ์๊ฐ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ํ์๋ฅผ ์ง์ํด์ผ ํฉ๋๋ค.