Функциональное программирование на Python для самых маленьких — Часть 1 — Lambda Функция

image

Я решил написать эту серию статей, ибо считаю, что никто не должен сталкиваться с той стеной непонимания, с которой столкнулся когда-то я.

Ведь большинство статей написаны таки образом что, для того чтобы понять что-то в Функциональном Программировании (далее ФП), тебе надо уже знать многое в ФП. Эту статью я старался написать максимально просто — настолько понятно, чтобы её суть мог уловить мой племянник, школьник, который сейчас делает свои первые шаги в Python.

Небольшое введение


Для начала, давайте разберемся, что такое функциональное программирование, в чем его особенности, зачем оно было придумано, а также где и как его использовать. Стоп… А зачем? Об этом написаны тонны материалов, да и в этой статье судя по всему эта информация не особо нужна. Эта статья написана для того, чтобы читатели научились разбираться в коде, который написан в функциональном стиле. Но если вы все-таки хотите разобраться в истории Функционального Программирования и в том, как оно работает под капотом, то советую вам почитать о таких вещах, как

  • Чистая Функция
  • Функции высшего порядка

Давайте кратко разберемся в этих двух понятиях прежде чем продолжим.

Чистая Функция — Функция которая является детерминированной и не обладает никакими побочными эффектами.

То есть чтобы функция являлась чистой она должна быть детерминированной — то есть каждый раз при одинаковом наборе аргументов выдавать одинаковый результат.

Пример детерминированной функции

def sum(a,b):
  return a+b

print(sum(3,6))
print(sum(3,6))
print(sum(3,6))

>>>9
>>>9
>>>9

И пример не детерминированной:

from datetime import date

todays_weekday = date.today().weekday()
def sum(a,b):
  if todays_weekday == 1:
    result = a+b
    print(f'sum is {result} and result class is {type(result)}')
  else:
    result = str(a+b)
    print(f'sum is {result} and result class is {type(result)}')

sum(4,5)
todays_weekday = 4
sum(4,5)

>>>sum is 9 and result class is <class 'int'>
>>>sum is 9 and result class is <class 'str'>

Каждый раз при смене дня недели (который не является аргументом функции) функция выдает разные результаты.

Самый очевидный пример не детерминированной функции это random:

import random
print(random.random())
print(random.random())
print(random.random())

>>>0.5002395668892657
>>>0.8837128676460416
>>>0.5308851462814731

Второе важное качество чистой функции это отсутствие побочных эффектов.

Покажем наглядно:

my_list = [32,3,50,2,29,43]

def sort_by_sort(li):
  li.sort()
  print(li)

sort_by_sort(my_list)
print(my_list)

>>>[2, 3, 29, 32, 43, 50]
>>>[2, 3, 29, 32, 43, 50]

Функция sort_by_sort имеет побочные эффекты потому что изменяет исходный список элементов и выводит что то в консоль.

my_list = [32,3,50,2,29,43]

def sort_by_sorted(li):
  return sorted(li)

print(sort_by_sorted(my_list))
print(my_list)

>>>[2, 3, 29, 32, 43, 50]
>>>[32, 3, 50, 2, 29, 43]

В отличии от предыдущего примера функция sort_by_sorted не меняет исходного массива и возвращает результат не выводя его в консоль самостоятельно.

Чистые функции хороши тем что:

  • Они проще читаются
  • Они проще поддерживаются
  • Они проще тестируются
  • Они не зависят от того в каком порядке их вызывать

Функциональное программирование можно охарактеризовать тем что в нем используются только чистые функции.

Функции высшего порядка — в программировании функция, принимающая в качестве аргументов другие функции или возвращающая другую функцию в качестве результата.

Пример ФВП:

def func(num):
  return num**2

def higher_order_func(fun, num):
  return fun(num)+fun(num)

print(func(4))
print(higher_order_func(func,4))

>>>16
>>>32

С основами чуть чуть разобрались и теперь перейдем к следующему шагу.

Итак, начнем


Для начала надо понять следующее — что такое Функциональное Программирование вообще. Лично я знаю две самые часто упоминаемые парадигмы в повседневном программировании — это ООП и ФП.

Если упрощать совсем и объяснять на пальцах, то описать эти две парадигмы можно следующим образом:

  • ООП — это Объектно Ориентированное Программирование — подход к программированию, при использовании которого объекты можно передавать в качестве параметров и использовать их в качестве значений.
  • По такой логике можно установить, что ФП — подход к программированию, при использовании которого функции можно передавать другим функциям в качестве параметров и использовать функции в качестве значений, возвращаемых другими функциями… Ответ скрыт в самом названии.

Как говорил мой любимый учитель zverok Виктор Шепелев: «Вся работа в программировании — это работа с данными. Взял какие-то данные, поигрался с ними и вернул обратно.»

Это относится и к ФП — взял какие-то данные, взял какую-то функцию, поигрался с ними и выдал что-то на выходе.

Не стану расписывать всё, иначе это будет оооочень долго. Цель данной статьи — помочь разобраться, а не объяснить, как и что работает, поэтому тут мы рассмотрим основные функции из ФП.

В большинстве своем ФП (как я его воспринимаю) — это просто упрощенное написание кода. Любой код, написанный в функциональном стиле, может быть довольно легко переписан в обычном стиле без потери качества, но более примитивно. Цель ФП заключается в том, чтобы писать код более простой, понятный и который легче поддерживать, а также который занимает меньше памяти, ну и куда же без этого — разумеется, главная вечная мораль программирования — DRY (Don’t Repeat Yourself — Не повторяйся).

Сейчас мы с вами разберем одну из основных функций, которая применяется в ФП — Lambda функцию.

В следующих статьях мы разберем такие функции как Map, Zip, Filter и Reduce.

Lambda функция


Lambda — это инструмент в python и других языках программирования для вызова анонимных функций. Многим это скорее всего ничего не скажет и никак не прояснит того, как она работает, поэтому я расскажу вам просто механизм работы lambda выражений.

Все очень просто.

Рассмотрим пример. Например, нам надо написать функцию которая бы считала площадь круга при известном радиусе.

Формула площади круга это

S = pi*(r**2)

где
S — это площадь круга
pi — математическая константа равная 3.14 которую мы получим из стандартной библиотеки Math
r — радиус круга — единственная переменная которую мы будем передавать нашей функции

Круг с радиусом

Теперь оформим это все в python:

import math #Подключаем библиотеку math

pi_const = round(math.pi, 2) #округляем pi до второго знака после запятой иначе она будет выглядеть как 3.141592653589793 а нам это будет неудобно

# Пишем функцию которая будет вычислять площадь круга по заданному радиусу в обычном варианте записи
def area_of_circle_simple(radius):
  return pi_const*(radius**2)

print(area_of_circle_simple(5))
print(area_of_circle_simple(12))
print(area_of_circle_simple(26))
>>>78.5
>>>452.16
>>>2122.64

Вроде бы неплохо, но это всё может выглядеть куда круче, если записывать это через lambda:

import math #Подключаем библиотеку math

pi_const = round(math.pi, 2) #округляем pi до второго знака 
# после запятой иначе она будет выглядеть 
# как 3.141592653589793 а нам это будет неудобно

print((lambda radius: pi_const*(radius**2))(5))
print((lambda radius: pi_const*(radius**2))(12))
print((lambda radius: pi_const*(radius**2))(26))

>>>78.5
>>>452.16
>>>2122.64

Чтобы было понятнее, анонимный вызов функции подразумевает то, что вы используете её, нигде не объявляя, как в примере выше.

Лямбда функция работает по следующему принципу


print((lambda перечисляются аргументы через запятую : что то с ними делается)(передаем аргументы))

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


Рассмотрим пример с двумя входными аргументами. Например, нам надо посчитать объем конуса по следующей формуле:

V = (height*pi_const*(radius**2))/3

Конус с габаритами

Запишем это все в python:

import math #Подключаем библиотеку math

pi_const = round(math.pi, 2) #округляем pi до второго знака после запятой иначе она будет выглядеть как 3.141592653589793 а нам это будет неудобно

#Формула объема конуса в классической форме записи
def cone_volume(height, radius):
  volume = (height*pi_const*(radius**2))/3
  return volume

print(cone_volume(3, 10))

>>>314.0

А теперь как это будет выглядеть в lambda форме:

import math #Подключаем библиотеку math

pi_const = round(math.pi, 2) #округляем pi до второго знака после запятой иначе она будет выглядеть как 3.141592653589793 а нам это будет неудобно

print((lambda height, radius : (height*pi_const*(radius**2))/3)(3, 10))

>>>314.0

Количество переменных здесь никак не ограничено. Для примера посчитаем объем усеченного конуса, где у нас учитываются 3 разные переменные.

Объем усеченного конуса считается по формуле:

V = (pi_const*height*(r1**2 + r1*r2 + r2**2))/3

Усеченный конус с габаритами

И вот, как это будет выглядеть в python классически:

import math #Подключаем библиотеку math

pi_const = round(math.pi, 2) #округляем pi до второго знака после запятой иначе она будет выглядеть как 3.141592653589793 а нам это будет неудобно

#Формула объема усеченного конуса в классической записи
def cone_volume(h,r1,r2):
  return (pi_const * h * (r1 ** 2 + r1 * r2 + r2 ** 2))/3

print(cone_volume(12, 8, 5))
print(cone_volume(15, 10, 6))
print(cone_volume(20, 12, 9))

>>>1620.24
>>>3077.20
>>>6970.8

А теперь покажем, как это будет выглядеть с lambda:

import math #Подключаем библиотеку math

pi_const = round(math.pi, 2) #округляем pi до второго знака после запятой иначе она будет выглядеть как 3.141592653589793 а нам это будет неудобно

print((lambda height, radius1, radius2 : (height*pi_const*(radius1**2 + radius1*radius2 + radius2**2))/3)(12, 8, 5))
print((lambda height, radius1, radius2 : (height*pi_const*(radius1**2 + radius1*radius2 + radius2**2))/3)(15, 10, 6))
print((lambda height, radius1, radius2 : (height*pi_const*(radius1**2 + radius1*radius2 + radius2**2))/3)(20, 12, 9))

>>>1620.24
>>>3077.20
>>>6970.8

После того, как мы разобрались, как работает lambda функция, давайте разберем ещё кое-что интересное, что можно делать с помощью lambda функции, что может оказаться для вас весьма неожиданным — Сортировку.

Сортировать одномерные списки в python с помощью lambda довольно глупо — это будет выглядеть, как бряцание мускулами там, где оно совсем не нужно.

Ну серьезно допустим, у нас есть обычный список (не важно состоящий из строк или чисел) и нам надо его отсортировать — тут же проще всего использовать встроенную функцию sorted(). И в правду, давайте посмотрим на это.

new_int_list = [43,23,56,75,12,32] # Создаем список чисел
print(sorted(new_int_list)) # Сортируем список чисел
new_string_list = ['zum6z', 'yybt0', 'h1uwq', '2k9f9', 'hin9h', 'b0p0m'] # Создаем список строк
print(sorted(new_string_list)) # Сортируем список строк

>>>[12, 23, 32, 43, 56, 75]
>>>['2k9f9', 'b0p0m', 'h1uwq', 'hin9h', 'yybt0', 'zum6z']

В таких ситуациях, действительно, хватает обычного sorted() (ну или sort(), если вам нужно изменить текущий список на месте без создания нового, изменив исходный).

Но что, если нужно отсортировать список словарей по разным ключам? Тут может быть запись как в классическом стиле, так и в функциональном. Допустим, у нас есть список книг вселенной Песни Льда и Пламени с датами их публикаций и количеством страниц в них.

Как всегда, начнем с классической записи.

# Создали список из словарей книг
asoiaf_books = [
  {'title' : 'Game of Thrones', 'published' : '1996-08-01', 'pages': 694},
  {'title' : 'Clash of Kings', 'published' : '1998-11-16', 'pages': 761},
  {'title' : 'Storm of Swords', 'published' : '2000-08-08', 'pages': 973},
  {'title' : 'Feast for Crows', 'published' : '2005-10-17', 'pages': 753},
  {'title' : 'Dance with Dragons', 'published' : '2011-07-12', 'pages': 1016}
]

# Функция по получению названия книги
def get_title(book):
    return book.get('title')

# Функция по получению даты публикации книги
def get_publish_date(book):
    return book.get('published')

# Функция по получению количества страниц в книге
def get_pages(book):
    return book.get('pages')

# Сортируем по названию
asoiaf_books.sort(key=get_title)
for book in asoiaf_books:
  print(book)
print('-------------')
# Сортируем по датам
asoiaf_books.sort(key=get_publish_date)
for book in asoiaf_books:
  print(book)
print('-------------')
# Сортируем по количеству страниц
asoiaf_books.sort(key=get_pages)
for book in asoiaf_books:
  print(book)

>>>{'title': 'Clash of Kings', 'published': '1998-11-16', 'pages': 761}
>>>{'title': 'Dance with Dragons', 'published': '2011-07-12', 'pages': 1016}
>>>{'title': 'Feast for Crows', 'published': '2005-10-17', 'pages': 753}
>>>{'title': 'Game of Thrones', 'published': '1996-08-01', 'pages': 694}
>>>{'title': 'Storm of Swords', 'published': '2000-08-08', 'pages': 973}
>>>-------------
>>>{'title': 'Game of Thrones', 'published': '1996-08-01', 'pages': 694}
>>>{'title': 'Clash of Kings', 'published': '1998-11-16', 'pages': 761}
>>>{'title': 'Storm of Swords', 'published': '2000-08-08', 'pages': 973}
>>>{'title': 'Feast for Crows', 'published': '2005-10-17', 'pages': 753}
>>>{'title': 'Dance with Dragons', 'published': '2011-07-12', 'pages': 1016}
>>>-------------
>>>{'title': 'Game of Thrones', 'published': '1996-08-01', 'pages': 694}
>>>{'title': 'Feast for Crows', 'published': '2005-10-17', 'pages': 753}
>>>{'title': 'Clash of Kings', 'published': '1998-11-16', 'pages': 761}
>>>{'title': 'Storm of Swords', 'published': '2000-08-08', 'pages': 973}
>>>{'title': 'Dance with Dragons', 'published': '2011-07-12', 'pages': 1016}

А теперь перепишем это все через lambda функцию:

# Создали список из словарей книг
asoiaf_books = [
  {'title' : 'Game of Thrones', 'published' : '1996-08-01', 'pages': 694},
  {'title' : 'Clash of Kings', 'published' : '1998-11-16', 'pages': 761},
  {'title' : 'Storm of Swords', 'published' : '2000-08-08', 'pages': 973},
  {'title' : 'Feast for Crows', 'published' : '2005-10-17', 'pages': 753},
  {'title' : 'Dance with Dragons', 'published' : '2011-07-12', 'pages': 1016}
]

# Сортируем по названию
for book in sorted(asoiaf_books, key=lambda book: book.get('title')):
  print(book)

print('-------------')

# Сортируем по датам
for book in sorted(asoiaf_books, key=lambda book: book.get('published')):
  print(book)

print('-------------')

# Сортируем по количеству страниц
for book in sorted(asoiaf_books, key=lambda book: book.get('pages')):
  print(book)

>>>{'title': 'Clash of Kings', 'published': '1998-11-16', 'pages': 761}
>>>{'title': 'Dance with Dragons', 'published': '2011-07-12', 'pages': 1016}
>>>{'title': 'Feast for Crows', 'published': '2005-10-17', 'pages': 753}
>>>{'title': 'Game of Thrones', 'published': '1996-08-01', 'pages': 694}
>>>{'title': 'Storm of Swords', 'published': '2000-08-08', 'pages': 973}
>>>-------------
>>>{'title': 'Game of Thrones', 'published': '1996-08-01', 'pages': 694}
>>>{'title': 'Clash of Kings', 'published': '1998-11-16', 'pages': 761}
>>>{'title': 'Storm of Swords', 'published': '2000-08-08', 'pages': 973}
>>>{'title': 'Feast for Crows', 'published': '2005-10-17', 'pages': 753}
>>>{'title': 'Dance with Dragons', 'published': '2011-07-12', 'pages': 1016}
>>>-------------
>>>{'title': 'Game of Thrones', 'published': '1996-08-01', 'pages': 694}
>>>{'title': 'Feast for Crows', 'published': '2005-10-17', 'pages': 753}
>>>{'title': 'Clash of Kings', 'published': '1998-11-16', 'pages': 761}
>>>{'title': 'Storm of Swords', 'published': '2000-08-08', 'pages': 973}
>>>{'title': 'Dance with Dragons', 'published': '2011-07-12', 'pages': 1016}

Таким образом, lambda функция хорошо подходит для сортировки многомерных списков по разным параметрам.

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

Но где же тут та самая экономия места, времени и памяти? Экономится максимум пара строк.

И вот тут мы подходим к реально интересным вещам.

Которые разберем в следующей статье, где мы обсудим map функцию.

UPD: По многочисленным просьбам, расставил знаки препинания.
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 25

    +2
    Эту статью я старался написать максимально просто

    Не использовать запятые — это все-таки уже лишнее упрощение.
      +3

      Популяризация ФП – это, конечно, хорошо, но в таком виде я бы слона не купил...


      Цель ФП заключается в том чтобы писать код более простой, понятный и который легче поддерживать а также который занимает меньше памяти ну и куда же без этого — разумеется главная новая мораль программирования DRY (Don’t Repeat Yourself — Не повторяйся).

      А цель ООП – писать сложный, непонятный и неподдерживаемый код? А этой "главной новой морали" уже больше 20 лет (The Pragmatic Programmer: From Journeyman to Master, 1999 г.) При том, что самому ФП еще больше.


      Замена def на lambda – это не ФП. И даже "такие функции как Map, Zip, Filter и Reduce" не сделают императивный код функциональным.

        0
        Поясните пожалуйста где я противопоставлял ФП и ООП? В большинстве своем все развитие программирования в последние десятилетия вело к упрощению работы и разработке подходов которые делали код более понятным и легко поддерживаемым — так же как и ООП и ФП и все другие методологии
          +2

          Складывается такое впечатление из пункта "Итак, начнем":


          Лично я знаю две самые часто упоминаемые парадигмы в повседневном программировании — это ООП и ФП.
          ООП – это…
          ФП – это…
          В большинстве своем ФП (как я его воспринимаю) это просто упрощенное написание кода. Любой код написанный в функциональном стиле может быть довольно легко переписан в обычном без потери качества но более примитивно. Цель ФП заключается в том...

          Что для вас "обычный" стиль?


          Но, собственно, это не основной посыл моего комментария. Код, который вы показали – это обычная императивная лапша, только с lambda вместо def. К ФП это имеет весьма отдаленное отношение.


          Плюс к этому, ФП код не всегда "более простой" (может быть и наоборот, императивный аналог оказывается более простым для понимания) и не всегда "занимает меньше памяти".

        +1
        Вроде бы неплохо но это все может выглядеть куда круче если записывать это через lambda

        PEP8 не рекомендует присваивать имена лямбдам.
          –1
          Статья рассчитана на совсем начинающих и я привожу примеры того как лямбда может использоваться анонимно без объявления
            +6
            «Статья» лишь запутывает и отпугивает «начинающих». Она лишь наглядно показывает, что «все эти лямбды совершенно ненужная заумь, которая ничего не меняет, но всё усложняет».
              0

              «Совсем начинающим» не стоит лазить в лямбды: это грузит их девственный мозг лишним сахаром, отвлекая от формирования нужных извилин — алгоритмического мышления, например. По своему опыту преподавания должен сказать, что лямбды (а также for-else и другие сладости) стоит давать не раньше, чем ученики съедят хотя бы щенка на обычных def-ах.

            +2
            Explicit is better than implicit.
            Simple is better than complex.

            Не злоупотребляйте лямбдами, если нужен поддерживаемый код. Анонимные функции в некоторых случаях можно применять как колбеки. В подавляющем большинстве случаев стоит передавать именованую функцию/класс в качестве колбека.


            # пример с django-моделями, псевдокод
            @transaction.atomic
            def create_view(request):
                dataset = json.loads(request.content)
                related_dataset = dataset.pop('related')
                instance = MyModel(**dataset)
                related_instances = map(RelatedModel, related_dataset)
                instance.related_set.set(related_instances)
                instance.save()
                return 201

            Для случаев с параметризироваными функциями покрываются методом partial из модуля functools:


            import functools
            import operator
            
            mul_8 = map(functools.partial(operator.mul, 8), range(10))
              0
              Автор, приведите, пожалуйста, пример лямбда-функции, которая расставляет в тексте запятые и дефисы для наиболее часто встречаемых союзов и частиц.
                +1
                По многочисленным просьбам я добавил знаки препинания в текст статьи
                  +2

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

                    0
                    Офтоп конечно, но разве не может чистая функция менять переменную? Ведь что записать в новую ячейку памяти, что записать в уже существующую — с точки зрения сайд-эффектов выглядит одинаково…
                    Просто у меня свое детство
                      0
                      Нет.
                        0
                        Хорошо, немного подробнее объясню свою точку зрения… Сайд-эффекты — это то, что мы не можем контролировать, например функция не просто вычисляет нужное нам значение, но и меняет что-то «на стороне». То есть это аналогично тому, как если бы функция зависела от какого-то стейта, который мы ей явно не передаем. А значит сайд-эффект — это тоже самое, но наоборот.
                          0
                          А теперь ещё раз перечитайте определение «чистой» функции — ответ станет очевидным. Нет, не имеет права. По определению.
                            0

                            Чистая функция вообще не должна ничего никуда писать, ни в новую ячейку, ни в существующую. Чистая функция просто возвращает результат.

                              0
                              AlexBrown А теперь ещё раз перечитайте определение «чистой» функции — ответ станет очевидным. Нет, не имеет права. По определению.
                              Читаюлюбые действия работающей программы, изменяющие среду выполнения. Тогда почему перезапись считается побочным эффектом, лишающим функцию ее чистоты, а создание новой копии нет (ведь новая копия — это тоже изменение среды выполнения)?

                              Значит чистая функция просто должна возвращать результат (ookami_kb). А перезапись или создание новой копии — это всегда сайд-эффект. Тогда почему второе в ФП принимается, а первое нет?
                                0

                                Ну тут надо определиться с контекстом. С исходным заявлением "записывает результат в новую ячейку памяти" я не согласен – поэтому и написал, что чистая функция не должна ничего никуда писать. А просто создание новой копии – это не изменение среды (ну если оставаться на уровне языка программирования, не вмешивая физические процессы в компьютере – иначе, строгих математически чистых функций мы в принципе не получим).


                                Вообще, мне кажется, проще всего объяснить чистую функцию через 2 условия:


                                1. Она всегда возвращает одно и то же значение, если вызывать с одними и теми же параметрами.
                                2. Вызов функции можно заменить на ее результат без каких-либо последствий (ссылочная прозрачность).
                                  0
                                  проще всего объяснить чистую функцию через 2 условия:....
                                  Да, я тоже так думаю.

                                  А просто создание новой копии – это не изменение среды
                                  Разве? Ведь эта копия где-то же хранится…
                                    0
                                    Ведь эта копия где-то же хранится

                                    Ну да, поэтому я и сделал потом оговорку, что мы остаемся на уровне "языка", не вдаваясь в подробности, что хранение копия во временной переменной – это работа с оперативной памятью, а значит тоже операция ввода-вывода. Иначе всё ФП так и останется на уровне красивой математической абстракции...

                                      0
                                      Осталось мне понять, чем хранение в оперативной памяти лучше хранения на диске…
                                        0

                                        Если вы готовы смириться с тем, что


                                        • чтение/запись будет синхронным и блокирующим;
                                        • любая ошибка чтения/записи будет крэшить программу;
                                        • вы не перезаписываете файлы, а только создаете новые (по крайней мере, пока данные в "области видимости");
                                        • вы явно получаете и возвращаете дескриптор файла, а не "внезапно" читаете этот файл (или пишете в него) внутри функции,

                                        то, пожалуй, ничем.

                          0
                          Нет, на то она и чистая функция. Она не должна менять значение никаких переменных кроме как в своей области видимости. Сама функция ничего не записывает в ячейки памяти вне себя, возвращаемый ею результат может быть записан в новую переменную согласно принципу immutable
                        0

                        Я только начинаю изучать программирование, занимаюсь буквально пару месяцев, то есть, как я понял, именно на меня рассчитана эта статья. И, скажу честно, она абсолютно не выполняет своей цели.
                        Она не дала мне абсолютно никакого понимания того, что такое ФП, хотя Вы вначале сказали, что и не ставите себе такую задачу, но пытаться объяснить как работает ФП без понимания, что это вообще такое — как минимум странно.
                        Само содержание также вызывает у меня вопросы — примеры использования лямбда функций ну очень простые. Мне кажется, любая статья, документация, видео в ютуб объясняют как минимум в той же мере, если не больше. По крайней мере я абсолютно ничего нового не узнал. И совершенно не понял, как это связано с функциональными программированием.
                        Я прошу прощения за такой негативный комментарий, но я надеюсь, что критика была достаточно объективной и поможет Вам писать лучше, потому что, мне кажется, статьи для начинающих должны быть очень высокого качества — новичка легко запутать, ввести в заблуждение или отбить все желание учиться.

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое