Как вы берете часть списка в OCaml / ReasonML? - PullRequest
0 голосов
/ 26 октября 2018

Например, в Ruby вы можете сделать что-то вроде:

list = ["foo", "bar", "baz", "qux", "quux", "corge"]
result = list[2..4]

И result будет содержать ["baz", "qux", "quux"].

Как бы вы сделали это в OCaml / ReasonML?

Ответы [ 3 ]

0 голосов
/ 30 октября 2018

Если у вас есть доступ к библиотекам Belt, вы можете сделать что-то вроде:

open Belt;

let myList = ["first", "second", "third", "fourth", "fifth", "sixth"];

/* To get 2..4 */
myList
  ->List.drop(2)
  ->Option.getWithDefault([])
  ->List.take(3)
  ->Option.getWithDefault([])
  ->Js.log;

/* Gives you the list ["third", "fourth", "fifth"] */
0 голосов
/ 08 ноября 2018

Нет встроенной функции для нарезки списка, но это можно сделать легко. Поскольку у нас есть начальная точка и конечная точка, мы можем разбить проблему на две части. Первая часть - это drop несколько элементов, пока мы не достигнем начальной точки, а вторая часть - это take несколько элементов от начальной точки до конечной точки.

let rec drop = (n, list) =>
  switch (list) {
  | [] => []
  | [_, ...xs] as z => n == 0 ? z : drop(n - 1, xs)
  };

let rec take = (n, list) =>
  switch (list) {
  | [] => []
  | [x, ...xs] => n == 0 ? [] : [x, ...take(n - 1, xs)]
  };

теперь, когда у нас есть эти две функции, мы можем объединить их, чтобы отбросить начальные элементы от до начальной точки drop(i, list), а затем передать этот новый список, чтобы перенести элементы из начальной точки в конечную точку

take(k - i + 1, drop(i, list));

всего

let slice = (list, i, k) => {

  let rec drop = (n, list) =>
    switch (list) {
    | [] => []
    | [_, ...xs] as z => n == 0 ? z : drop(n - 1, xs)
    };

  let rec take = (n, list) =>
    switch (list) {
    | [] => []
    | [x, ...xs] => n == 0 ? [] : [x, ...take(n - 1, xs)]
    };

  take(k - i + 1, drop(i, list));
};

Лучшим подходом было бы предоставить начальную точку и затем диапазон, а не конечную точку, потому что здесь мы не ограничиваем, что конечная точка должна быть больше начальной точки

let slice = (list, start, range) => {

  let rec drop = (n, list) =>
    switch (list) {
    | [] => []
    | [_, ...xs] as z => n == 0 ? z : drop(n - 1, xs)
    };

  let rec take = (n, list) =>
    switch (list) {
    | [] => []
    | [x, ...xs] => n == 0 ? [] : [x, ...take(n - 1, xs)]
    };

  take(range, drop(start, list));
};
0 голосов
/ 26 октября 2018

Специальных языковых обозначений для нарезки OCaml не существует. Вы можете написать свою функцию, скажем, используя сопоставление с образцом, или объединить head с функциями take (они доступны в стандартных библиотеках). Для Reason объедините List.hd и List.tk https://reasonml.github.io/api/List.html, также модуль Array имеет подсписок Array.sub. OCaml обсуждался здесь как получить подсписок из списка в ocaml

...