Standard ML

**Standard ML**-ը (**SML**), ընդհանուր նշանակության, մոդուլյար, ֆունկցիոնալ ծրագրավորման լեզու է՝ կոմպիլյացիայի ժամանակ տիպերի ստուգման և տիպերի ավտոմատ դուրսբերման ներդրված մեխանիզմներով։ Այն առավել հայտնի է կոմպիլյատորների ստեղծման, ծրագրավորման լեզուների հետազոտման, ինչպես նաև թեորեմների ավտոմատ ապացուցման ոլորտներում)
։

SML-ը «Հաշվարկելի ֆունկցիաների տրամաբանություն» թեորեմների ավտոմատ ապացուցման նախագծում օգտագործվող ML ծրագրավորման լեզվի ժամանակակից զարգացումն է։

## Լեզվի կառուցվածքը
Standard ML-ը ֆունկցիոնալ ծրագրավորման լեզու է՝ որոշ ոչ-ֆուկցիոնալ (իմպերատիվ) տարրերով։ SML լեզվով գրված ծրագրերը բաղկացած են հաշվարկման ենթակա արտահայտություններից, որոնցից որոշները վերադարձնում են հատուկ `unit` տիպի արժեք և հաշվարկվում են միայն կողմնակի էֆեկտներ ստանալու համար։

Ինչպես բոլոր ֆունկցիոնալ ծրագրավորման լեզուներում, SML-ի կարևորագույն բաղադրիչը ֆունկցիան է, որն էլ օգտագործվում է որպես հիմնական աբստրակցիայի մեխանիզմ։ Օրինակ, հայտնի ֆակտորիալ կարելի է արտահայտել հետևյալ կերպ.


```sml
fun factorial n = 
  if n = 0 then 1 else n * factorial (n-1)
```


SML-ի կոմպիլյատորը այս ֆունկցիայի համար ստատիկ եղանակով դուրս է բերում int -> int տիպը։ Այսինքն, այն եզրակացնում է, որ եթե n-ը օգտագործված է միայն ամբողջաթիվ արտահայտության մեջ, ապա ինքն էլ պետք է ամբողջ թիվ լինի, հետևաբար, արժեքը ձևավորող ամբողջ արտահայտության տիպը նույնպես պետք է ամբողջաթիվ լինի։

Նույն ֆունկցիան կարելի է արտահայտել նաև *տարբերակներով ֆունկցիայի սահմանումով*, որտեղ *if*-*then*-*else* պայմանը փոխարինված է ֆակտորիալ ֆունկցիայի առանձին արժեքները հաշվող շաբլոնների հաջորդականությամբ։ `|` նիշով իրարից անջատված այդ շաբլոնները հաջորդաբար դիտարկվում են այնքան ժամանակ, քանի դեռ համապատասխանություն չի հայտնաբերվել.


```sml
fun factorial 0 = 1
  | factorial n = n * factorial (n - 1)
```


Նույնը կարելի է ձևակերպել նաև `case` կառուցվածքի օգտագործմամբ.


```sml
val rec factorial =
  fn n => case n of 0 => 1
 | n => n * factorial (n - 1)
```


Կամ լյամբդա-արտահայտության օգտագործմամբ.


```sml
val rec factorial = fn 0 => 1 | n => n * factorial(n -1)
```


Այստեղ `val` ծառայողական բառը կատարման միջավայր է ներմուծում նոր *անուն*—*արժեք* կապ (binding), իսկ `fn` կառուցվածքը ստեղծում է անանուն ֆունկցիայի նոր սահմանում։

Լոկալ ֆունկցիայի օգտագործմամբ ֆակտորիալը սահմանող ֆունկցիան կարելի է սահմանել ավելի արդյունավետ տարբերակով՝ *վերջին կանչի ռեկուրսիայի* կիրառումով.

```sml
fun factorial n = let
 fun lp (0, acc) = acc
  | lp (m, acc) = lp (m-1, m*acc)
 in
  lp (n, 1)
 end
```


(`let`-արտահայտության արժեքը `in` և `end` բառերի միջև ընկած արտահայտության արժեքն է։) Մեկ կամ ավելի կուտակող (ակումուլյատոր) պարամետրերով վերջին կանչով (tail-call) ռեկուրսիվ ֆունկցիայի պարփակումը ինվարիանտներից ազատ արտաքին ֆունկցիայիում, ինչպես կատարված է այստեղ, Standard ML լեզում ընդունված հնարք է և բավականին հաճախ է հանդիպում SML ծրագրերում։

### Տիպի հոմանիշ
*Տիպի հոմանիշը* սահմմանվում է `type` ծառայողական բառով։ Ստորև հարթության կետի համար սահմանված է տիպի հոմանիշ։ Սահմանված են նաև երկու կետերի հեռավորությունը և գագաթներով տրված եռանկյան մակերեսը Հերոնի բանաձևով հաշվող ֆունկցիաները։

```sml
type loc = real * real

 fun dist ((x0, y0), (x1, y1)) = let
 val dx = x1 - x0
 val dy = y1 - y0
 in
  Math.sqrt (dx * dx + dy * dy)
 end

 fun heron (a, b, c) = let
 val ab = dist (a, b)
 val bc = dist (b, c)
 val ac = dist (a, c)
 val perim = ab + bc + ac
 val s = perim / 2.0
 in
  Math.sqrt (s * (s - ab) * (s - bc) * (s - ac))
 end
```


### Բարձր կարգի ֆունկցիաներ
Ֆունկցիաները կարող են արգումենտում ստանալ այլ ֆունկցիաներ.

```sml
fun applyToBoth f x y = (f x, f y)
```


ֆունկցիաները որպես արդյունք կարող են վերադարձնել ֆունկցիաներ.

```sml
fun constantFn k = let
 fun const anything = k
  in
 const
  end
```


(այլ կերպ)

```sml
fun constantFn k = (fn anything => k)
```


Ֆունկցիաները կարող են միաժամանակ ստանալ և վերադարձնել ֆունկցիաներ.

```sml
fun compose (f, g) = let
 fun h x = f (g x)
  in
 h
  end
```

(այլ կերպ)

```sml
fun compose (f, g) = (fn x => f (g x))
```


Հիմնական գրադարանի `List.map` ֆունկցիան Standard ML լեզվում առավել հաճախ օգտագործվող բարձր կարգի ֆունկցիաներից է

```sml
fun map _ [] = []
  | map f (x::xs) = f x :: map f xs
```

(`map` ֆունկցիայի ավելի արդյունավետ իրականացումը կարող է սահմանվել հետևյալ կերպ.)

```sml
fun map f xs = let
 fun m ([], acc) = List.rev acc
 | m (x::xs, acc) = m (xs, f x :: acc)
  in
 m (xs, [])
  end
```


### Բացառություններ
Բացառությունները գործարկվում (ստեղծվում) են `raise` ծառայողական բառով, և մշակվում են շաբլոնների համապատասխանեցման `handle` կառուցվածքով։

```sml
exception Undefined
 fun max [x] = x
  | max (x::xs) = let val m = max xs in if x > m then x else m end
  | max [] = raise Undefined
 fun main xs = let
 val msg = (Int.toString (max xs)) handle Undefined => "empty list...there is no max!"
  in
 print (msg ^ "\n")
  end
```


## Իրականացումներ
* **Standard ML of New Jersey** (SML/NJ) — ամբողջական կոմպիլյատոր և ինտերպրետատոր է, գրադարաններ, գործիքներ և փաստաթղթեր։ http://www.smlnj.org/
* **Moscow ML** — Caml լեզվի միջուկի օգտագործմամբ իրականացված կոմպիլյատոր է։ Իրականացված է ամբողջ Standard ML ստանդարտը, մոդուլների համակարգը, Basis գրադարանի մեծ մասը։ http://www.itu.dk/people/sestoft/mosml.html

## Ծանոթագրություններ