์ ๋์จ ์ฝ๋ ์์ฑ์ ๊ธฐ๋ณธ ์ํฌํ๋ก๋ฅผ ๋ฐ๋ผ๊ฐ๋ฉฐ UCM ์ฌ์ฉ๋ฒ, ํ๋ก์ ํธ์ ๋ค์์คํ์ด์ค, ์ฝ๋ ํ์, ์คํฌ๋์น ํ์ผ, ํ ์คํธ, ์ฝ๋ ์ ๋ฐ์ดํธ ๋ฐ ๊ณต์ ๊น์ง ์ดํด๋ด ๋๋ค.
์ด ๋ฌธ์๋ ์ ๋์จ(Unison) ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ธฐ๋ณธ ์ํฌํ๋ก๋ฅผ ๋จ๊ณ๋ณ๋ก ์๋ดํฉ๋๋ค. ์งํํ๋ฉด์ ์ ๋์จ ํต์ฌ ์ธ์ด์ ๊ทธ ๋ฌธ๋ฒ์ ์ฌ๋ฌ ์กฐ๊ฐ์ ํจ๊ป ์๊ฐํฉ๋๋ค. ๊ถ๊ธํ ์ ์ด ์๊ฑฐ๋ ๋ ๊น์ด ๋ฐฐ์ฐ๊ณ ์ถ๋ค๋ฉด ์ ๋์จ ์ธ์ด ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
์ด ๊ฐ์ด๋๋ ์ด๋ฏธ ํต์คํํธ ๊ฐ์ด๋์ ๋จ๊ณ๋ฅผ ๋ฐ๋ผ ์๋ฃํ๊ณ , ํต์ฌ ์์ด๋์ด๋ฅผ ํ ๋ฒ ํ์ด๋ณด์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
์ ๋์จ ์ฝ๋๋ฒ ์ด์ค ๋งค๋์ (Unison Codebase Manager), ์ค์ฌ์ UCM์ ์ ๋์จ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ฅผ ์คํํ๊ณ , ์์ฑํ ์ ๋์จ ์ฝ๋์ ์ํธ์์ฉํ ์ ์๊ฒ ํด ์ฃผ๋ ์ปค๋งจ๋๋ผ์ธ ๋๊ตฌ์ ๋๋ค. UCM์ ์ ๋์จ ์ฝ๋๋ฒ ์ด์ค์ ์ํธ์์ฉํ๋ ์ธํฐํ์ด์ค ์ญํ ์ ํฉ๋๋ค.
UCM์ ์ฃผ์ ์ญํ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
๐ก ๊ธฐ์ตํด ๋์ธ์: ์ ๋์จ ์ฝ๋๋ ํ ์คํธ ๊ธฐ๋ฐ ํ์ผ ๋ด์ฉ์ผ๋ก ์ ์ฅ๋์ง ์์ต๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ ๋์จ ํ๋ก๊ทธ๋จ์ ๋ณ๊ฒฝํ๊ณ ์คํํ๊ธฐ ์ํด ์ด๋ฐ ๋๊ตฌ๊ฐ ํ์ํฉ๋๋ค.
ํฐ๋ฏธ๋์์ ucm ์ ์
๋ ฅํด ์์ํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ucm ์ ํ ๋๋ ํฐ๋ฆฌ์ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ์๋ก ๋ง๋ค๊ฑฐ๋ ๊ธฐ์กด ๊ฒ์ ์ฝ๋๋ค.
๋ค์์ ์ ๋์จ ์ฝ๋๋ฒ ์ด์ค ๋งค๋์ ๊ฐ ์์๋๋ฉด์ ์ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ์ด๊ธฐํํ๋ ๋ชจ์ต์ ๋๋ค:
textNow starting the Unison Codebase Manager (UCM)... [โฆ] Get started: ๐ Type help to list all commands, or help <cmd> to view help for one command ๐จ Type ui to open the Codebase UI in your default browser ๐ Read the official docs at https://www.unison-lang.org/docs/ ๐ Visit Unison Share at https://share.unison-lang.org to discover libraries ๐ I'm watching for changes to .u files under ~/unisonCode scratch/main>
์ฐ๋ฆฌ๋ ๋ณดํต ์ฝ๋๋ฒ ์ด์ค๋ฅผ, ์ฐ๋ฆฌ๊ฐ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ ๋๋ง๋ค ์์ ๋๋ ํ ์คํธ ํ์ผ๋ค์ ๋ฌถ์์ผ๋ก ์๊ฐํฉ๋๋ค. ํ์ง๋ง ์ ๋์จ์์๋ ์ฝ๋๋ฒ ์ด์ค๊ฐ ์ด CLI์ ๋์์ ๋ฐ์ ํ๋ก๊ทธ๋๋ฐ์ ์ผ๋ก ์ ์ฅ๋๊ณ ๊ฐฑ์ ๋ฉ๋๋ค.
์ ๋์จ ์ฝ๋๋ฒ ์ด์ค ํฌ๋งท์๋ ๋ช ๊ฐ์ง ์ค์ํ ํน์ง์ด ์์ต๋๋ค:
์ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๋ง๋๋ ๊ฒฝ์ฐ, ํ๋กฌํํธ > ๋ scratch/main ์ผ๋ก ํ์๋ฉ๋๋ค. ์ด๋ ํ์ฌ ์์
์ค์ธ ํ๋ก์ ํธ์ ๋ธ๋์น ์ด๋ฆ์ ๋ํ๋ด๋ฉฐ, ์ด์ด์ ์ด ๋ ๊ฐ๋
์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ ํ๋ฆฌ์ผ์ด์ ๋ง๋ค ์ฝ๋๋ฒ ์ด์ค๋ฅผ ์ฌ๋ฌ ๊ฐ ๋ง๋๋ ๋์ , ์ ๋์จ์ ํ๋์ ์ฝ๋๋ฒ ์ด์ค๋ฅผ "ํ๋ก์ ํธ(project)" ๋จ์๋ก ๋๋๋๋ค. ์ ๋์จ ํ๋ก์ ํธ๋ ์์ค ์ฝ๋ ์ ์ฅ์(repository)์ ํด๋นํฉ๋๋ค. ํ๋ก์ ํธ๋ ์ฝ๋๋ฅผ ์ฑ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ, ๊ทธ๋ฆฌ๊ณ ํ์ ์ด ํ์ํ ์ ์๋ ๊ธฐํ ์์ ์ผ๋ก ๋ถ๋ฆฌํฉ๋๋ค. ํ๋ก์ ํธ๋ ๋ค์ ๋ ๋ฆฝ์ ์ธ ์์ ํ๋ฆ์ ๋ํ๋ด๋ ๋ธ๋์น๋ค๋ก ๋๋ฉ๋๋ค.
ํ๋ก์ ํธ ์์์ ์ฝ๋๋ ๋ค์์คํ์ด์ค(namespace)๋ก ๋ฌถ์
๋๋ค. ๋ค์์คํ์ด์ค๋ ์ ๋์จ ํญ๊ณผ ํ์
์, ์ปดํจํฐ์ ๋๋ ํฐ๋ฆฌ์ ๋น์ทํ ํธ๋ฆฌ ๊ตฌ์กฐ๋ก ๊ตฌ์ฑํฉ๋๋ค. ์๋ฅผ ๋ค์ด math.sqrt ๋ผ๋ ์ด๋ฆ์ math ๋ค์์คํ์ด์ค ์์ sqrt ์ ์๋ฅผ ๊ฐ๋ฆฌํต๋๋ค. ์ ์๋ ์ (.)์ผ๋ก ๊ตฌ๋ถ๋๋ ์ฌ๋ฌ ๋ค์์คํ์ด์ค ์ธ๊ทธ๋จผํธ๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค. ์: base.Optional.Some.
UCM ์ฝ์์์ project.create ๋ช
๋ น์ผ๋ก ์ tour ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด ๋ด
์๋ค.
textscratch/main> project.create tour ๐ I've created the project tour. I'll now fetch the latest version of the base Unison library... ๐จ Type `ui` to explore this project's code in your browser. ๐ Discover libraries at https://share.unison-lang.org ๐ Use `help-topic projects` to learn more about projects. Write your first Unison code with UCM: 1. Open scratch.u. 2. Write some Unison code and save the file. 3. In UCM, type `update` to save it to your new project. ๐ ๐ฅณ Happy coding! tour/main>
ํ๋กฌํํธ๊ฐ tour/main> ์ผ๋ก ๋ฐ๋ ๊ฒ์ ์ฃผ๋ชฉํ์ธ์. ํ์ฌ ํ๋ก์ ํธ๋ ์ด์ tour ์ด๊ณ , ํ์ฌ ๋ธ๋์น๋ /main ์
๋๋ค. ์ด ํ๋ก์ ํธ์ ๋ธ๋์น์ ๋ฒ์(scope)๊ฐ ํ์ ๋ ์ํ๋ก UCM ๋ช
๋ น๊ณผ ์ฝ๋๊ฐ ์๋ํฉ๋๋ค.
์ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค๋ฉด, UCM์ ์๋์ผ๋ก base ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํด ์ค๋๋ค. ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ lib ๋ผ๋ ํน๋ณํ ๋ค์์คํ์ด์ค์ ์์นํฉ๋๋ค.
๐ง
lib ๋ค์์คํ์ด์ค๋ UCM์ด ํ๋ก์ ํธ์ ๋ชจ๋ ์์กด์ฑ์ ์ค์นํ๋ ๊ณณ์
๋๋ค. ํญ์ ํ๋ก์ ํธ ๋ฃจํธ ๋ฐ๋ก ์๋์ ์์นํฉ๋๋ค.
์ด์ ๋ฐฉ๊ธ ๋ด๋ ค๋ฐ์ base ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ํ๋ฉด์, ์ ๋์จ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ํ์ํ๋ ๋ฐฉ๋ฒ์ ์ต์ํด์ ธ ๋ด
์๋ค.
ls ๋ช
๋ น์ผ๋ก ๋ค์์คํ์ด์ค ์์ ํญ๊ณผ ํ์
์ด๋ฆ์ ๋ณผ ์ ์์ต๋๋ค.
texttour/main> ls lib.base.data.List
์ถ๋ ฅ์ ์ ์๋ค๊ณผ ํด๋น ์๊ทธ๋์ฒ(signature)๊ฐ ๋ฒํธ์ ํจ๊ป ๋์ด๋ ๋ชฉ๋ก์ ๋๋ค.
texttour/main> ls lib.base.data.List 1. ++ ([a] -> [a] -> [a]) 2. ++. (1 term) 3. +: (a -> [a] -> [a]) [โฆ]
์ ๋์จ ์ฝ๋๋ UCM์ ํตํด ์ ์ฅ๋๊ธฐ ๋๋ฌธ์, ๋ค์๊ณผ ๊ฐ์ ์ ๋ณด๋ฅผ ์บ์ํ๊ณ ์กฐํํ ์ ์์ต๋๋ค:
์ค์ ๋ก find ์ view ๋ช
๋ น์ผ๋ก ๊ฒ์๊ณผ ์ฝ๋ ๋ณด๊ธฐ๋ฅผ ์ง์ ํด ๋ณด๊ฒ ์ต๋๋ค:
texttour/main> find reverse I couldn't find matches in this namespace, searching in 'lib'... 1. lib.base.data.Graph.reverse : Graph v ->{Exception} Graph v 2. lib.base.data.Graph.tests.reverse : [Result] 3. lib.base.data.List.Nonempty.reverse : List.Nonempty a -> List.Nonempty a 4. lib.base.data.List.reverse : [a] -> [a]
find ๋ช
๋ น์ ์ด๋ฆ์ reverse ๊ฐ ํฌํจ๋ ์ ์๋ค์ ์ฐพ์ต๋๋ค. ๋จผ์ ํ๋ก์ ํธ ์์ ์ฐ๋ฆฌ ์ฝ๋์์ ๊ฒ์ํ ๋ค์, lib ์์ ๊ฒ์ํฉ๋๋ค.
texttour/main> view List.reverse lib.base.data.List.reverse : [a] -> [a] lib.base.data.List.reverse as = List.foldLeft (acc a -> a +: acc) [] as
์ฌ๊ธฐ์๋ view ๋ช
๋ น์ผ๋ก ํจ์์ ์์ค ์ฝ๋๋ฅผ ์ดํด๋ณด์์ต๋๋ค.
์ด์ ์ ๋์จ ๋ฌธ๋ฒ์ ์กฐ๊ธ ์๊ฐํด ๋ณด๊ฒ ์ต๋๋ค:
List.reverse : [a] -> [a] ๋ ํ์
์๊ทธ๋์ฒ์ ๋ํ ๋ฌธ๋ฒ์
๋๋ค. ํ์
์๊ทธ๋์ฒ๋ ์ ๋์จ์์ ์ ์ ์์ ์์ฑ๋ฉ๋๋ค. : ๊ธฐํธ๋ "ํ์
์ด ~์ด๋ค"๋ผ๊ณ ์ฝ์ต๋๋ค. ์๋ฅผ ๋ค์ด, "reverse ์ ํ์
์ [a] -> [a] ์ด๋ค"๋ผ๋ ์๋ฏธ์
๋๋ค.[ ] ๋ ์ ๋์จ์์ ๋ฆฌ์คํธ(list)๋ฅผ ๋ํ๋
๋๋ค.[a] -> [a] ๋, ์ด๋ค ํ์
์ ์์๋ค๋ก ์ด๋ฃจ์ด์ง ๋ฆฌ์คํธ๋ฅผ ๋ฐ์์ ๊ฐ์ ํ์
์ ๋ฆฌ์คํธ๋ฅผ ๋ฐํํ๋ ํจ์๋ผ๋ ๋ป์
๋๋ค.List.reverse as ๋ ํจ์์ ๋จ์ผ ์ธ์๋ฅผ as ๋ผ๋ ์ด๋ฆ์ผ๋ก ๋ฐ๋๋ค๋ ๋ป์
๋๋ค. = ๋ค์ ๋์ค๋ ๋ชจ๋ ๊ฒ์ด ํจ์ ๋ณธ๋ฌธ์
๋๋ค. ์ฌ๊ธฐ์๋ ๊ณต๋ฐฑ(๋ค์ฌ์ฐ๊ธฐ)์ผ๋ก ๊ตฌ๋ถ๋๋ ๋ธ๋ก์
๋๋ค.(acc a -> ..) ๋ ์ต๋ช
ํจ์(๋๋ค)์ ๋ํ ๋ฌธ๋ฒ์
๋๋ค.(acc a -> ...) [] as ๋ List.foldLeft ์ ์ ๋ฌ๋๋ ์ธ ๊ฐ์ ์ธ์์
๋๋ค.โจ
view ๋ช
๋ น์ ์ธ์ ์์ด ์
๋ ฅํ๋ฉด, ์ฝ๋๋ฒ ์ด์ค ์ ์๋ฅผ ์ฐพ์ ์ ์๋ fzf ๊ฒ์ ์ธํฐํ์ด์ค๊ฐ ์ด๋ฆฝ๋๋ค. ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๋น ๋ฅด๊ฒ ํ์ํ๊ณ ์ด๋ฆ์ผ๋ก ์ ์๋ฅผ ์ฐพ๋ ์ข์ ๋ฐฉ๋ฒ์
๋๋ค.
์ฝ๋๋ฒ ์ด์ค ๋งค๋์ ๋ ํ์ฌ ๋๋ ํฐ๋ฆฌ ์์ .u ๋ก ๋๋๋ ๋ชจ๋ ํ์ผ ๋ณ๊ฒฝ์ ๊ฐ์ํฉ๋๋ค. ์ด๋ฐ ํ์ผ์ด ์ ์ฅ๋ ๋๋ง๋ค(์ด๋ฅผ "์คํฌ๋์น ํ์ผ"์ด๋ผ๊ณ ๋ถ๋ฆ
๋๋ค), ์ ๋์จ์ ๊ทธ ํ์ผ์ ํ์ฑํ๊ณ ํ์
๊ฒ์ฌ๋ฅผ ์ํํฉ๋๋ค.
ucm ์ด ์คํ ์ค์ธ ํฐ๋ฏธ๋์ ๊ทธ๋๋ก ๋๊ณ , ์ ํธํ๋ ํ
์คํธ ์๋ํฐ์์ scratch.u (๋๋ foo.u ๊ฐ์ ๋ค๋ฅธ ์ด๋ฆ๋ ๊ด์ฐฎ์ต๋๋ค) ํ์ผ์ ์๋ก ์ฌ์ธ์.
์คํฌ๋์น ํ์ผ์ ๋ค์ ๋ด์ฉ์ ์์ฑํฉ๋๋ค:
unisonsquare : Nat -> Nat square x = use Nat * x * x
์ด๋ square ๋ผ๋ ํจ์๋ฅผ ์ ์ํฉ๋๋ค. ์ด ํจ์๋ x ๋ผ๋ ์ธ์๋ฅผ ๋ฐ๊ณ , x ๋ฅผ ์๊ธฐ ์์ ๊ณผ ๊ณฑํ ๊ฐ์ ๋ฐํํฉ๋๋ค.
use Nat * ๋ ์ด๋ค * ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ ์ง ์ง์ ํ๋ use ์ ์
๋๋ค. ์ด ์ฐ์ฐ์๋ lib.base ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ Nat ๋ค์์คํ์ด์ค์ ์ ์๋ ๊ฒ์
๋๋ค. use ์ ๋๋ถ์ base.Nat ๋ฅผ ๊ฐ๋จํ Nat ๋ก, * ๋ฅผ Nat.* ๋ผ๊ณ ์ ๋์ฌ๋ฅผ ๋ถ์ด์ง ์๊ณ ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํ์ผ์ ์ ์ฅํ๋ฉด, ์ ๋์จ์ ์ด ๋ณ๊ฒฝ์ ์ ์ฉํ ์ ์๋์ง ์ฌ๋ถ๋ฅผ ์๋ ค ์ค๋๋ค:
textI found and typechecked these definitions in ~/unisoncode/scratch.u. If you do an `update`, here's how your codebase would change: โ New definitions: square : Nat -> Nat
square ๋ฅผ ์ฝ๋๋ฒ ์ด์ค์ ์ ์ฅํ๊ธฐ ์ ์, ์คํฌ๋์น ํ์ผ scratch.u ์์์ ๋ฐ๋ก ํ ๋ฒ ํธ์ถํด ๋ณด๊ฒ ์ต๋๋ค. > ๋ก ์์ํ๋ ํ ์ค์ ์ถ๊ฐํ์ธ์:
unisonsquare : Nat -> Nat square x = use Nat * x * x > square 4
ํ์ผ์ ์ ์ฅํ๋ฉด, ์ ๋์จ์ ๋ค์๊ณผ ๊ฐ์ด ์ถ๋ ฅํฉ๋๋ค:
text6 | > square 4 โงฉ 16
6๋ฒ์งธ ์ค์ > square 4 ๋ "watch ํํ์"์ด๋ผ๊ณ ๋ถ๋ฆ
๋๋ค. ์ ๋์จ์ ๋ณ๋์ ์ฝ๊ธฐ-ํ๊ฐ-์ถ๋ ฅ ๋ฃจํ(REPL)๋ฅผ ๋๋ ๋์ , watch ํํ์์ ์ฌ์ฉํด ์ฝ๋ ํ์ผ ์์์ ์ง์ ์ฝ๋๋ฅผ ์คํํฉ๋๋ค. ์คํฌ๋์น ํ์ผ๊ณผ ํ๋ก์ ํธ ์์ ์๋ ๋ชจ๋ ๊ฒ์ด ์ค์ฝํ ์์ ๋ค์ด์ค๋ฏ๋ก, ํ
์คํธ ์๋ํฐ์ ๋ชจ๋ ๊ธฐ๋ฅ์ ํ์ฉํ๋ฉด์ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋์์ ํ
์คํธํ ์ ์์ต๋๋ค.
์ง๋ฌธ: ๊ฐ ๊ณ์ฐ ๋น์ฉ์ด ํฐ ๊ฒฝ์ฐ์๋, ์ ์ฅํ ๋๋ง๋ค ๋ชจ๋ watch ํํ์์ ๋ค์ ํ๊ฐํด์ผ ํ ๊น์? ์ ๋์จ์ ์ด๋ฅผ ํผํ๊ธฐ ์ํด, ๊ฐ ํํ์์ ํด์๋ฅผ ํค๋ก ์ฌ์ฉํ๋ ์บ์๋ฅผ ๋ก๋๋ค. ํด์๊ฐ ๋ฐ๋์ง ์๋๋ค๋ฉด, ์ ๋์จ์ ์บ์๋ ๊ฒฐ๊ณผ๋ฅผ ์ฌ์ฌ์ฉํฉ๋๋ค. ์ธ์ ๋ ์ง ์บ์๋ฅผ ์ง์๋ ๋ฌธ์ ์์ต๋๋ค. .u ํ์ผ์ ์คํ๋ ๋์ํธ์ฒ๋ผ ์๊ฐํด ๋ณด์ธ์ โ ์์กด์ฑ์ด ๋ฐ๋ ์
๋ง ๋ค์ ๊ณ์ฐ๋ฉ๋๋ค.
๐ค
์ด ๋ฐฉ์์ด ํจ๊ณผ์ ์ผ๋ก ๋์ํ๊ฒ ํด ์ฃผ๋ ๋ง์ง๋ง ์ฌ๋ฃ๋ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๋๋ค. ํํ์์ ๋ถ์ํจ๊ณผ(side effect)๊ฐ ์๋ค๋ฉด, ๊ทธ ๊ฒฐ๊ณผ๋ ๊ฒฐ์ ์ ์ด๋ฉฐ, ์ ๋์จ์ฒ๋ผ ๋ด์ฉ ๊ธฐ๋ฐ(content-based) ํด์๋ฅผ ํค๋ก ์ผ์ ์ ์๋ค๋ฉด ์ผ๋ง๋ ์ง ์บ์ํ ์ ์์ต๋๋ค. ์ ๋์จ์ ํ์ ์์คํ ์ ์ด๋ฌํ watch ํํ์ ์์์ I/O ๋ฅผ ์ํํ๊ฑฐ๋, ํ๊ฐํ ๋๋ง๋ค ๊ฒฐ๊ณผ๊ฐ ๋ฌ๋ผ์ง ์ ์๋ ๋ค๋ฅธ ์์ ์ ํ ์ ์๋๋ก ๋ง์ ์ค๋๋ค.
UCM์ด ์ด๋ป๊ฒ ๋ฐ์ํ๋์ง ํ์ธํ๊ธฐ ์ํด, ๋ ๋ง์ watch ํํ์์ ์ถ๊ฐํด ๋ณด์ธ์:
unison-- ์ ๋์จ์ด ๋ฌด์ํ๋ ์ฃผ์ > List.reverse [1,2,3,4] > 4 + 6 > 5.0 / 2.0 > not true
์ด์ square ํจ์์ ๋ํ ํ
์คํธ๋ฅผ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค:
unisontest> square.tests.ex1 = verify do ensureEqual (square 4) 16
test> ๋ square.tests.ex1 ์ด๋ผ๋ ์ด๋ฆ์ ํ
์คํธ watch ํํ์์ ๋์
ํฉ๋๋ค.
foo ์ ๋ํ ํ
์คํธ๋ foo.tests ์๋์ ๋ก๋๋ค. ๊ทธ๋ ์ง ์๋๋ผ๋ ์ด๋ฆ square.tests.ex1 ์์ฒด์ ํน๋ณํ ์๋ฏธ๊ฐ ์๋ ๊ฒ์ ์๋๋๋ค.test.verify ๋ ํ
์คํธ ๋์ ํจ์๋ฅผ ์์ ๊ฒฐ๊ณผ์ ํจ๊ป ํธ์ถํ๋ ์ง์ฐ ๊ณ์ฐ์ ๊ธฐ๋ํฉ๋๋ค.
do ๋ ์ง์ฐ ๊ณ์ฐ์ ์์ํฉ๋๋ค. ์ธ์๊ฐ ์๋ ํจ์, ์ฆ () -> a ์ฒ๋ผ, ๊ฒฐ๊ณผ๋ฅผ ๋์ค์(lazily) ๋ฐํํ๋ ํจ์๋ผ๊ณ ์๊ฐํ๋ฉด ๋ฉ๋๋ค.test.ensureEqual ์ ๋ ๊ฐ์ด ์๋ก ๋ค๋ฅด๋ฉด Exception ์ ๋ฐ์์์ผ ํ
์คํธ๋ฅผ ์คํจํ๊ฒ ํฉ๋๋ค.
ํ์ผ์ ์ ์ฅํ๋ฉด, UCM์ ๋ค์๊ณผ ๊ฐ์ด ์๋ตํฉ๋๋ค:
text8 | test> square.tests.ex1 = verify do ensureEqual (square 4) 16 โ Passed
์ด์ ์ด ํจ์๋ฅผ ์กฐ๊ธ ๋ ์ฒ ์ ํ๊ฒ ํ
์คํธํด ๋ด
์๋ค. square ๋ ๋ชจ๋ a, b ์ ๋ํด square a * square b == square (a * b) ๋ผ๋ ์์ฑ์ ๊ฐ์ ธ์ผ ํฉ๋๋ค. ์ ๋์จ ํ
์คํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ด๋ฐ ์์ฑ ๊ธฐ๋ฐ(property-based) ํ
์คํธ ์์ฑ์ ์ง์ํฉ๋๋ค. ์๋์๋ ์ ๋ฌธ๋ฒ์ด ์กฐ๊ธ ๋ฑ์ฅํ๋๋ฐ, ๋ค์์ ์ค๋ช
ํฉ๋๋ค:
unisontest> square.tests.prop1 = verify do Each.repeat 100 a = Random.natIn 0 100 b = Random.natIn 0 100 ensure (square a * square b == square (a * b))
์ด ์ฝ๋๋ Each ์ Random ๋ฅ๋ ฅ(ability)์ ์ฌ์ฉํด ๋ค์ํ ์
๋ ฅ์ผ๋ก ํจ์๋ฅผ ํ
์คํธํฉ๋๋ค. Each ๋ 100๊ฐ์ Random ์ซ์๋ฅผ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋๋ฉฐ, ํ
์คํธ๋ ๊ทธ ๊ฐ๋ค์ ๊ฒ์ฆํฉ๋๋ค.
= ๋ค์ ์์๋๋ ์ ๋์จ ์ฝ๋ ๋ธ๋ก์๋ ๊ฐ์ ๋ค์ฌ์ฐ๊ธฐ ์์ค์ ๋ฐ์ธ๋ฉ(a = โฆ)์ ์ฌ๋ฌ ๊ฐ ๋ ์ ์์ต๋๋ค. ๋ง์ง๋ง ํํ์(ensure (square โฆ))์ด ๊ทธ ๋ธ๋ก์ ๊ฒฐ๊ณผ์
๋๋ค.do ํค์๋๋ ๊ณต๋ฐฑ์ผ๋ก ๊ฒฝ๊ณ๊ฐ ์ ํด์ง๋ ์ง์ฐ ๊ณ์ฐ ์ฝ๋ ๋ธ๋ก์ ์์ํฉ๋๋ค.์คํฌ๋์น ํ์ผ์ ์ ์ฅํด, ์ด ์์ฑ ํ ์คํธ๊ฐ ์ฑ๊ณตํ๋์ง ํ์ธํ์ธ์.
square ํจ์์ ๊ทธ ํ
์คํธ๋ค์ ์์ง ์ฝ๋๋ฒ ์ด์ค์ ์ผ๋ถ๊ฐ ์๋๋๋ค. ์ง๊ธ๊น์ง๋ ์คํฌ๋์น ํ์ผ ์์๋ง ์กด์ฌํฉ๋๋ค. ์ด์ ์ด๋ค์ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค. UCM์ผ๋ก ๋์๊ฐ์ update ๋ฅผ ์
๋ ฅํฉ๋๋ค:
texttour/main> update โ I've added these definitions: square : Nat -> Nat square.tests.ex1 : [Result] square.tests.prop1 : [Result]
UCM์์ view square.tests.prop1 ์ ์
๋ ฅํด ๋ณด์ธ์.
texttour/main> view square.tests.prop1 square.tests.prop1 : [Result] square.tests.prop1 = test.verify do use Nat * == use Random natIn Each.repeat 100 a = natIn 0 100 b = natIn 0 100 ensure (square a * square b == square (a * b))
์ ๋์จ์ ์ฝ๋๋ฅผ ๋ ๋๋งํ ๋ ์ ํํ use ๋ฌธ์ ์ฝ์
ํ๊ณ , ์์ฒด pretty-print ๊ท์น์ ๋ฐ๋ผ ํฌ๋งทํ
ํฉ๋๋ค.
UCM ํ๋กฌํํธ์์ test ๋ฅผ ์
๋ ฅํด ํ
์คํธ ์ค์ํธ๋ฅผ "์คํ"ํด ๋ณด์ธ์:
texttour/main> test Cached test results (`help testcache` to learn more) โ square.tests.ex1 : Passed โ square.tests.prop1 : Passed โ 2 test(s) passing Tip: Use view square.tests.ex1 to view the source of a test.
์ฝ์์๋ ํ ์คํธ ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ๋์ง๋ง, ์ค์ ๋ก ์ฝ๋๋ฅผ ๋ค์ ์คํํ ๊ฒ์ ์๋๋๋ค! ํ ์คํธ๋ ์ด์ ์ ์ด๋ฏธ ์คํ๋์๊ณ , ์ ๋์จ ํด์์ ๋ฐ๋ผ ์บ์๋์ด ์์ต๋๋ค. ์ ๋์จ ๊ฐ์ ์์ ํจ์ํ ์ธ์ด์์, ์ด๋ฐ ํ ์คํธ๋ค์ ๊ฒฐ์ ์ ์ด๊ธฐ ๋๋ฌธ์, ๊ทธ๋ค์ด ์์กดํ๋ ์ฝ๋๊ฐ ๋ฐ๋๊ธฐ ์ ๊น์ง๋ ์ค์ ๋ก ๋ค์ ์คํ๋์ง ์์ต๋๋ค.
์ด์ square ์ ๊ทธ ํ
์คํธ๋ค์ move ๋ช
๋ น์ผ๋ก ํ๋ก์ ํธ์ ๋ค๋ฅธ ์์น๋ก ์ฎ๊ฒจ ๋ด
์๋ค. move ๋ ์ฌ๊ท์ ์ผ๋ก ์๋ํ๋ฏ๋ก, ํญ๊ณผ square ๋ค์์คํ์ด์ค ์์ ๋ชจ๋ ๊ฒ๋ค์ ์ ์ด๋ฆ์ผ๋ก ์ฎ๊น๋๋ค.
texttour/main> move square mySquare Done.
์ดํ, ์ธ์ ์์ด find ๋ฅผ ์ฌ์ฉํ๋ฉด ํ์ฌ ๋ค์์คํ์ด์ค ์๋์ ๋ชจ๋ ์ ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค:
texttour/main> find 1. mySquare : Nat -> Nat 2. mySquare.tests.ex1 : [Result] 3. mySquare.tests.prop1 : [Result]
๋ค์ test ๋ฅผ ์คํํด ๋ณด๋ฉด, ์ฌ์ ํ ํ
์คํธ ๊ฒฐ๊ณผ๊ฐ ์บ์๋์ด ์๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค! ์ ์๋ ์ด๋ฆ์ด ์๋๋ผ ๊ตฌํ์ ์ํด ์๋ณ๋๊ธฐ ๋๋ฌธ์
๋๋ค.
texttour/main> test Cached test results (`help testcache` to learn more) โ mySquare.tests.ex1 : Passed โ mySquare.tests.prop1 : Passed โ 2 test(s) passing
์ด์ mySquare ํจ์์ ๊ตฌํ์ ๋ฐ๊ฟ ๋ณด๊ฒ ์ต๋๋ค.
์คํฌ๋์น ํ์ผ scratch.u ๋งจ ์์ ์ ์ค์ ๋ง๋ค๊ณ ๋์ ์ธ ๊ฐ, --- ๋ฅผ ์
๋ ฅํฉ๋๋ค. ์ด๋ฅผ ํด๋(fold)๋ผ๊ณ ๋ถ๋ฆ
๋๋ค. --- ์๋์ ์๋ ๋ชจ๋ ๋ด์ฉ์ UCM์ด ๋ฌด์ํฉ๋๋ค.
๊ทธ๋ฐ ๋ค์ UCM์์ edit mySquare ๋ฅผ ์
๋ ฅํฉ๋๋ค:
texttour/main> edit mySquare โ๏ธ I added 1 definition to the top of ~/unisoncode/scratch.u You can edit them there, then run `update` to replace the definitions currently in this branch.
์ด ๋ช
๋ น์ mySquare ์ pretty-print๋ ์ ์๋ฅผ ์คํฌ๋์น ํ์ผ ๋งจ ์์ ์ถ๊ฐํฉ๋๋ค.
์ด์ mySquare x ๋ฅผ, ์ฌ๋ฏธ ์ผ์, ์ฒ์ x ๊ฐ์ ํ์์ ํฉ์ผ๋ก ์ ์ํด ๋ณด๊ฒ ์ต๋๋ค. (์ด ๋ฐฉ์์ด ์๋ ์ ๊ณฑ๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ฃผ๋ ์ด์ ์ ๋ํ ๋ฉ์ง ๊ธฐํํ์ ์ค๋ช
์ด ์์ต๋๋ค.)
unisonuse base mySquare : Nat -> Nat mySquare x = sum (map (x -> x * 2 + 1) (range 0 x)) sum : [Nat] -> Nat sum = foldLeft (+) 0
ํ์ผ์ ์ ์ฅํ๋ฉด, UCM์ mySquare ๋ฅผ ์
๋ฐ์ดํธํด๋ ๊ด์ฐฎ๋ค๋ ๋ฉ์์ง๋ฅผ ํ์ํ ๊ฒ์
๋๋ค:
textI found and typechecked these definitions in ~/unisoncode/scratch.u. If you run `update`, here's how your codebase would change: โ These new definitions are ok to `update`: sum : [Nat] -> Nat โ These names already exist. You can `update` them to your new definition: mySquare : Nat -> Nat
์ด์ ์ค์ ๋ก update ๋ฅผ ์คํํด ๋ด
์๋ค:
texttour/main> update โ I've added these definitions: sum : [Nat] -> Nat โ I've updated these names to your new definition: mySquare : Nat -> Nat
update ์ ์ํฅ๋ฐ์ ํ
์คํธ๋ง ๋ค์ ์คํํ ์คํธ๋ฅผ ๋ค์ ์คํํด์ผ ํ๋์ง ์ฌ๋ถ๋ฅผ ํ๋จํ๋ ์์กด์ฑ ์ถ์ ์ 100% ์ ํํ๋ฉฐ, ๊ฐ๋ณ ์ ์ ๋จ์๋ก ์ถ์ ๋ฉ๋๋ค.
์ด์ ๋ค์ test ๋ช
๋ น์ ์คํํ๋ฉด, ์ค์ ๋ก ์์กด์ฑ์ด ๋ณ๊ฒฝ๋์๊ธฐ ๋๋ฌธ์ ํ
์คํธ๊ฐ ๋ ์ด์ ์บ์๋์ง ์์ต๋๋ค:
texttour/main> test โ New test results: โ mySquare.tests.ex1 : Passed โ mySquare.tests.prop1 : Passed โ 2 test(s) passing Tip: Use view 1 to view the source of a test.
๐
๋ง์ง๋ง์ผ๋ก ํด์ผ ํ ์ผ์ ์ ๋์จ ์ ฐ์ด(Unison Share)์ ๊ฐ์ ํ๋ ๊ฒ์ ๋๋ค. ์ ๋์จ ์ ฐ์ด๋ ์ ๋์จ์ ์ํ ์ฝ๋ ํธ์คํ ํ๋ซํผ์ผ๋ก, ์์ ์ ์ฝ๋์ ๋ํ ํ์ ์ ๊ด๋ฆฌํ๊ณ ์ ์ ๋์จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฐ๊ฒฌํ๋ ๊ณณ์ ๋๋ค. Unison Share๋ก ์ด๋ํด, ๋ก์ปฌ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ์ฝ๋ ํธ์คํ ์ ์ฐ๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ์๋ด์ ๋ฐ๋ผ ์งํํ์ธ์!
์ฝ๋๋ ์ ๋์จ์ ์์ฒด ์ฝ๋ ํธ์คํ
์๋ฃจ์
์ธ Unison Share์ push ๋ช
๋ น์ผ๋ก ํผ๋ธ๋ฆฌ์๋๋ฉฐ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ lib.install ๋ช
๋ น์ผ๋ก ์ค์น๋ฉ๋๋ค. ์์กด์ฑ์ ๊ด๋ฆฌํ๊ฑฐ๋ ์ฝ๋๋ฅผ ํผ๋ธ๋ฆฌ์ํ๊ธฐ ์ํด ๋ณ๋์ ๋๊ตฌ๊ฐ ํ์ํ์ง ์์ต๋๋ค. Unison Share ์์ ์ฝ๋ ํธ์คํ
๊ณผ ์ํธ์์ฉํ๋ ๊ธฐ๋ฅ์ ์ ๋ถ UCM์ ๋ด์ฅ๋์ด ์์ต๋๋ค.
์ ๋์จ ๋๋ฌ๋ณด๊ธฐ๋ฅผ ๋ง์น ๊ฒ์ ์ถํํฉ๋๋ค! ์ด์ ์ ๋์จ ์ฝ๋๋ฅผ ์ง์ ์์ฑํ ์ค๋น๊ฐ ๋์์ต๋๋ค. ๋ฌด์์ ๋ง๋ค์ด ๋ผ์ง ๊ธฐ๋ํ๊ณ ์์ต๋๋ค! ๐ฅณ