OCaml, F# последователни, каскадни let обвързвания

Типично за OCaml или F# е да има последователни let свързвания във формата:

let a1 = ...
let a2 = ...
let a3 = ...
let f1 = ...
let f2 = ...
let f3 = ... 
f3 a1 a2 a3

В много случаи някои от тези let обвързвания (напр. f1 и f2 в примера по-горе) се използват само като градивни елементи на израза или функцията непосредствено след тях и не се препращат отново след това. В други случаи някои стойности наистина се използват в края на „веригата“ (напр. a1, a2 и a3 в примера по-горе). Има ли някакъв синтактичен идиом, който да направи тези разлики в обхвата изрични?


person Marcus Junius Brutus    schedule 08.08.2012    source източник


Отговори (2)


On може да използва това, за да изясни, че temp се използва само в дефиницията на a1:

let a1 =
  let temp = 42 in
  temp + 2 in
let a2 = ...

Обхватът на temp наистина е ограничен до определението на a1.

Друг шаблон използва повторно същото име, за да скрие предишното му използване, като по този начин също така изяснява, че предишното използване е временно:

let result = input_string inchan in
let result = parse result in
let result = eval result in
result

Повторното използване на същото име обаче е спорно.

Разбира се винаги има коментари и празни редове:

let a1 = ...
let a2 = ...
let a3 = ...

(*We now define f3:*)
let f1 = ...
let f2 = ...
let f3 = ...

f3 a1 a2 a3

Редактиране: както беше посочено от fmr, аз също харесвам оператора на тръбата. Не е дефинирано по подразбиране в OCaml, използвайте

let (|>) x f = f x;;

След това можете да напишете нещо подобно

input_string inchan |> parse |> eval |> print
person jrouquie    schedule 08.08.2012
comment
И за да разширим това леко, ако temp се използва за изчисляване на множество стойности, можете да свържете тези стойности едновременно като кортеж: let a1, a2, a3 = let temp = ... in temp + 2, temp - 2, temp * 2 - person Daniel; 09.08.2012
comment
Освен това, в зависимост от сложността на изразите на RHS, можете да помислите за идиома за тръбопровод (e |› e |› e |› e) - person fmr; 09.08.2012

В допълнение към отговора на jrouquie, можете да избегнете даването на имена на междинни стойности чрез разумно използване на функционална композиция и други комбинатори. Особено харесвам следните три, предоставени от Batteries:

# let ( |> ) x f = f x;;
val ( |> ) : 'a -> ('a -> 'b) -> 'b = <fun>
# let ( |- ) f g x = g (f x);;
val ( |- ) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c = <fun>
# let flip f x y = f y x;;
val flip : ('a -> 'b -> 'c) -> 'b -> 'a -> 'c = <fun>

Малък пример за използване на |> е

# [1;2;3]
  |> List.map string_of_int
  |> String.concat "; "
  |> Printf.sprintf "[%s]";;
- : string = "[1; 2; 3]"

В крайна сметка ще имате нужда от |- и flip в по-реалистични примери. Това е известно като без точки или негласно програмиране.

person Ashish Agarwal    schedule 09.08.2012
comment
FWIW, |> е backport от F# и вярвам, че flip е от Haskell. - person J D; 21.01.2013