Каковы базовые понятия в функциональном программировании?

При использовании декоратора Вы заменяете одну функцию другим. Другими словами, если у Вас есть декоратор

def logged(func):
    def with_logging(*args, **kwargs):
        print(func.__name__ + " was called")
        return func(*args, **kwargs)
    return with_logging

тогда, когда Вы говорите

@logged
def f(x):
   """does some math"""
   return x + x * x

, это - точно то же, что

def f(x):
    """does some math"""
    return x + x * x
f = logged(f)

и Ваша функция f заменяется функцией with_logging. К сожалению, это означает, что, если Вы тогда говорите

print(f.__name__)

, это распечатает with_logging, потому что это - название Вашей новой функции. На самом деле при рассмотрении docstring для f это будет пробел, потому что with_logging не имеет никакого docstring, и таким образом, docstring, который Вы записали, не будет там больше. Кроме того, при рассмотрении результата pydoc для той функции он не будет перечислен как взятие одного аргумента x; вместо этого это будет перечислено как взятие *args и **kwargs, потому что это - то, что берет with_logging.

При использовании декоратора всегда означал терять эту информацию о функции, это будет серьезная проблема. Вот почему мы имеем functools.wraps. Это берет функцию, используемую в декораторе, и добавляет функциональность копирования по имени функции, docstring, списку аргументов, и т.д. И так как wraps самостоятельно декоратор, следующий код делает корректную вещь:

from functools import wraps
def logged(func):
    @wraps(func)
    def with_logging(*args, **kwargs):
        print(func.__name__ + " was called")
        return func(*args, **kwargs)
    return with_logging

@logged
def f(x):
   """does some math"""
   return x + x * x

print(f.__name__)  # prints 'f'
print(f.__doc__)   # prints 'does some math'
54
задан Matt Fenwick 9 October 2012 в 09:53
поделиться

5 ответов

В сообществе нет единого мнения относительно основных концепций функционального программирования. В Почему функциональное программирование имеет значение (PDF) , Джон Хьюз утверждает, что это функции высшего порядка и ленивое вычисление. В Wearing the Hair Shirt: Retrospective on Haskell Саймон Пейтон Джонс говорит, что главное - не лень, а чистота. Ричард Берд согласился бы. Но есть целая толпа программистов Scheme и ML, которые совершенно счастливы писать программы с побочными эффектами.

Как человек, который практиковал и преподавал функциональное программирование в течение двадцати лет, я могу дать вам несколько идей, которые, по общему мнению, являются в основе функционального программирования:

  • В основе лежат вложенные функции первого класса с правильной лексической областью видимости. Это означает, что вы можете создать анонимную функцию во время выполнения, чьи свободные переменные могут быть параметрами или локальными переменными функции , включающей , и вы получаете значение, которое можете вернуть, поместить в структуры данных и т. д. (Это наиболее важная форма функций высшего порядка, но некоторые функции высшего порядка (например, qsort !) Могут быть написаны на C, который не является функциональным языком.)

  • Средства составления функции с другими функциями для решения проблем. Никто не делает это лучше, чем Джон Хьюз.

  • Многие функциональные программисты считают, что чистота (свобода от эффектов, включая мутации, ввод-вывод и исключения) лежит в основе функционального программирования. Многие функциональные программисты этого не делают.

  • Полиморфизм , реализуется ли он компилятором или нет, является основной ценностью функциональных программистов. Как ни странно, программисты на C ++ называют это понятие «универсальным программированием». который поддерживает очень общую форму анализа случая. Часто компилятор может сказать вам, если вы забыли случай. Я бы не хотел программировать без этой языковой особенности (роскошь, однажды выбранная, становится необходимостью).

64
ответ дан 7 November 2019 в 07:50
поделиться

In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the application of functions, in contrast to the imperative programming style, which emphasizes changes in state. Functional programming has its roots in the lambda calculus, a formal system developed in the 1930s to investigate function definition, function application, and recursion. Many functional programming languages can be viewed as embellishments to the lambda calculus. - Wikipedia

In a nutshell,

  1. Lambda Calculus
  2. Higher Order Functions
  3. Immutability
  4. No side-effects
40
ответ дан 7 November 2019 в 07:50
поделиться

Not directly an answer to your question, but I'd like to point out that "object-oriented" and functional programming aren't necessarily at odds. The "core concepts" you cite have more general counterparts which apply just as well to functional programming.

Encapsulation, more generally, is modularisation. All purely functional languages that I know of support modular programming. You might say that those languages implement encapsulation better than the typical "OO" variety, since side-effects break encapsulation, and pure functions have no side-effects.

Inheritance, more generally, is logical implication, which is what a function represents. The canonical subclass -> superclass relation is a kind of implicit function. In functional languages, this is expressed with type classes or implicits (I consider implicits to be the more general of these two).

Polymorphism in the "OO" school is achieved by means of subtyping (inheritance). There is a more general kind of polymorphism known as parametric polymorphism (a.k.a. generics), which you will find to be supported by pure-functional programming languages. Additionally, some support "higher kinds", or higher-order generics (a.k.a. type constructor polymorphism).

What I'm trying to say is that your "core concepts of OO" aren't specific to OO in any way. I, for one, would argue that there aren't any core concepts of OO, in fact.

14
ответ дан 7 November 2019 в 07:50
поделиться

Abstraction, the process of making a function by parameterizing over some part of an expression.

Application, the process of evaluating a function by replacing its parameters with specific values.

At some level, that's all there is to it.

3
ответ дан 7 November 2019 в 07:50
поделиться

Let me repeat the answer I gave at one discussion in the Bangalore Functional Programming group:

A functional program consists only of functions. Functions compute values from their inputs. We can contrast this with imperative programming, where as the program executes, values of mutable локации меняются. Другими словами, в C или Java переменная с именем X относится к месту, значение которого изменяется. Но в функционале программирование X - это имя значения (а не местоположение). Где угодно X находится в области видимости, имеет то же значение (т. Е. Ссылочно прозрачный). В FP функции также являются значениями. Их можно передать как аргументы для других функций. Это известно как функционал высшего порядка. программирование. Функции высшего порядка позволяют моделировать удивительное разнообразие узоры. Например, посмотрите на функцию карты в Лиспе. Это представляет собой шаблон, в котором программисту нужно что-то сделать, чтобы каждый элемент списка. Это «что-то» закодировано как функция и передается в качестве аргумента карте.

Как мы видели, наиболее заметной особенностью FP является его побочный эффект. свобода. Если функция делает что-то большее, чем вычисление значения from it's input, then it is causing a side-effect. Such functions are not allowed in pure FP. It is easy to test side-effect free functions. There is no global state to set-up before running the test and there is no global state to check after running the test. Each function can be tested independently just by providing it's input and examining the return value. This makes it easy to write automated tests. Another advantage of side-effect freeness is that it gives you better control on parallelism.

Many FP languages treat recursion and iteration correctly. They does this by supporting something called tail-recursion. What tail-recursion is - if a function calls itself, and it is the last thing it does, it removes the current stack frame right away. In other words, if a function calls itself tail-recursively a 1000 times, it does not grow the stack a 1000 deep. This makes special looping constructs unnecessary in these languages.

Lambda Calculus is the most boiled down version of an FP language. Higher level FP languages like Haskell get compiled to Lambda Calculus. It has only three syntactic constructs but still it is expressive enough to represent any abstraction or algorithm.

My opinion is that FP should be viewed as a meta-paradigm. We can write programs in any style, including OOP, using the simple functional abstractions provided by the Lambda Calculus.

Thanks, -- Vijay

Original discussion link: http://groups.google.co.in/group/bangalore-fp/browse_thread/thread/4c2cfa7985d7eab3

4
ответ дан 7 November 2019 в 07:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: