Pull to refresh

Comments 27

Статья полезная, не спорю.

Есть только одна грубейшая ошибка, которая приводит к моментальному засыпанию читателей. У вас нет определения слов. Например, интересное слово «каррирование». Оно есть в вашем тексте, и встречается только в одном месте, при этом нигде не надо описание того, что же такое. Достаточно было бы даже ссылки на википедию, чтобы дать понять, о чём идёт речь.

Причём, не дано определение многих слов и словосочетаний. Конечно, вы можете ожидать, что читатель сам не дурак, и полезет в словари. Некоторые так и сделают, а другие закроют статью, если ещё и в карму не накакают. Просто люди ожидают понятных статей, особенно, если те претендуют на статус вводных.

Мой личный опыт преподавания в Вузе показал, что ежели студенты не врубились в смысл одного слова, то оставшуюся часть курса они просто не воспримут. Я не гнушаюсь никаких методов прояснения, начиная от гугла, заканчивая примерами «Вот банка колы — это экземпляр класс, а рука — это ссылка.»

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

Ну, и удачи в написании новых статей 8-) Они стоят того, чтобы быть 8-)
Хорошо, но ввести ФП и показать его отличие от императивного программирования лучше с исторической точки зрения: ФП языки идут от лямбда исчисления Алонзо Черча, а императивные от машины Тьюринга. Сравнив эти модели вычисления — сравним потомков.
Согласен, что сравнивать на уровне моделей вычислений — правильно, и именно так я делаю в преподаваемом в вузе курсе. Здесь же цель немного другая — научить программировать на функциональном языке. И имхо тут проще отталкиваться от простых примеров, а уже потом говорить про модели вычислений. Кстати, если говорить в историческом (хронологическом) плане, то сначала был подход (Беббидж), а уже потом — модель вычислений (Тьюринг).
let rec fact n =
  if n = 1 then 1
  else n*fact(n-1)
    in fact 5;;

F# не знаю, но «in fact 5» кажется лишним.
let rec fact n =
if n = 1 then 1
else n*fact(n-1);;

fact 5;;

Так тоже можно.
Как вы думаете, какая из функций вычисления факториала, приведенных в этом уроке, «лучше» — реализованная на C# или на F#?


Однозначно на C# — быстрее работает и не ест стек.
Боюсь, что C# версия больще 20! не вычислит. Про F# не знаю, но в свете всего этого скорость и поедание стека значения не имеет, так что надо искать другие критерии ;)
Ну а так как F# под .NET, то всё аналогично. Обе функции плохи, надо вообще табличкой, чисел-то всего ничего :)
F# в определенных случаях оптимизирует рекурсию и переделывает ее в цикл — см.пример ulfurinn ниже. Еще одним плюсом F# является вывод типов — функция переделывается под BigInt вписыванием одной аннотации типа.
Ну про хвостовую оптимизацию я в курсе.
Это даже императивные языки умеют (хотя, мб, не все).
В общем-то это я так, придрался :)
Стек, да. Так лучше? :)

let fact n =
  let rec fact_helper n a =
    if n = 1 then a
    else fact_helper (n-1) (a*n)
  in fact_helper n 1 ;;
О да! Выше я написал про сведение рекурсии к итерации, и еще напишу в дальнейших уроках.
Реализуйте функциональную программу для нахождения суммы числел от 1 до 100. Суммы квадратов этих чисел

let program = 5050;;
Похоже, что Вы написали программу для выдачи функциональной программы подсчета суммы квадратов чисел от 1 до 100.
Да похоже, но я написал функциональную программу:

let another_program x = x*(x+1)*(2*x+1)/6 in another_program 100;;

и произвел бета-редукцию с помощью калькулятора:

let another_program = 338350;;

=)
Невредно было бы начать с вопроса — в каких случаях использование еще одного языка вообще и функционального в частности может облегчить жизнь программисту? А то все чаще задумываешься над тем чтобы найти один язык который будешь знать действительно хорошо, вместо того чтобы помнить полдюжины и вечно между ними путаться
Всё просто — расширение кругозора.
Один писатель сказал (правда по другому поводу), что человек столько раз человек, сколько языков он знает.
Чем больше языков программирования (и парадигм) мы знаем, тем лучше сможем выбрать язык для конкретной задачи.
Не секрет, что много задач обработки массивов данных проще и красивее решается в функциональном стиле. Посмотрите на тот же LINQ в .NET
Глупо пытаться писать OS на LISP, но точно так же глупо пытаться анализировать данные на С.
Это сказал Гёте, емнип.
Мне кажется что вы как-то странно объясняете слово функция используя какие-то там операторы присваивания.

В функциональном программировании функция имеет математическое определение:
«Функция — это закон, по которому каждому значению элемента x из некоторого множества X ставится в соответствие единственный элемент y из множества Y.»

Если «доза», то подсаживаемся, а не влюбляемся :)
Интересно конечно, но где же интуитивное программирование? И почему ";;"?
Интересно, спасибо. Все разложенно по полочкам
Често говоря, мне как первый раз столкнувшемуся с функциональным программированием и кодом на F# практически ничего не понятно:
— что такое каррирование,
— почему пример вычисления факториала на императивном языке сделан так а не через рекурсия, хотя у вас была задача показать различия, и вы показали совсем не сравнимые вещи (ИМХО)
— что тут (let double x = x*2.0;;) значит слово double тип или название функции, что такое let, in и почему везде идут двойные точкизапятые ;;
— куда выводится в итоге результат вычислений
— и т.д. и т.д.

Думаю надо переделывать первый урок.
> что такое каррирование,

каррирование это представление функции от n аргументов в виде функции от n-1 аргумента. пример:

let sum x = fun y -> x + y;;

Короче, функции от нескольких аргументов это просто сахар над вложенными функциями.

> что тут (let double x = x*2.0;;) значит слово double тип или название функции, что такое let, in и почему везде идут двойные точкизапятые ;;

double это название функции. x это единственный аргумент функции. тело функции записывается после '='. так как функции в ФП все возвращают результат (хоть какой-то), то ключевое слово «return» опускается (оно как бы подразумевается). Две ;; означают конец определения функции (это просто синтаксис такой, мне тоже не сильно понятно, почему так).

let… in это полезная конструкция, которая позволяет разбивать выражения на подвыражения, и давать каждому подвыражению имя (то есть, теперь это переменная). Пример:

let x = 5 in x * x;;

PS рекомендую поиграться в интерпретаторе, так-то конечно ничего непонятно.
PPS я не знаю F# :)
Сидел мучался решил выложить может пнете если что не так:
open System

let discr a b c = b * b — 4.0 * a * c in
let roots a b c =
match discr a b c with
| d when d = 0.0 -> ((-b + sqrt d)/2.0*a,(-b — sqrt d)/2.0*a)
| d when d < 0.0 -> failwith «d < 0»
| d -> ((-b + sqrt d)/2.0*a,(-b — sqrt d)/2.0*a)
let res = roots 2.0 4.0 2.0

let rec Map f xs =
match xs with
| [] -> []
| y::ys -> f y :: Map f ys

let rec FoldLeft f xs acc =
match xs with
| [] -> acc
| y::ys -> FoldLeft f ys (f y acc)

let rec Sum a b = a + b
let double x = x * x
let doubles = Map double [1..100]
let doublesSumRes = FoldLeft Sum doubles 0
let sumRes = FoldLeft Sum [1..100] 0

let unCurried (x,y) = x + y
let curried x y = x + y

let curry f = fun x y -> f (x,y)
let unCurry f = fun (x, y) -> f x y

let toCurried = curry unCurried
let toUnCurried = unCurry curried
Sign up to leave a comment.

Articles