2016-12-08 4 views
0
increment([]) -> []; 
increment([H|T]) -> [H+1|increment(T)]. 

decrement([]) -> []; 
decrement([H|T]) -> [H-1|decrement(T)]. 

Итак, у меня есть этот код, но я не знаю, как они работают правильно, как в java.Каковы шаги при выполнении инкремента в erlang?

+0

Как и в предыдущем подобном вопросе: http://stackoverflow.com/questions/41008186/how-does-a-loop-simulation-works Вам интересно, как они отличаются? –

+0

Да, я действительно смущен T^T –

ответ

2

Java и Erlang - разные звери. Я не рекомендую делать сравнения с Java при изучении Erlang, особенно если Java - это единственный язык, который вы знаете до сих пор. Код, который вы опубликовали, является хорошим примером парадигмы, известной как «функциональное программирование». Я бы посоветовал сделать некоторые чтения по этому вопросу, чтобы помочь вам понять, что происходит. Чтобы попытаться сломать это, пока Эрланг идет, вам нужно понять, что функция Erlang полностью отличается от метода Java.

В Java ваша подпись метода состоит из имени метода и типов его аргументов. Тип возврата также может быть значительным. Метод Java increment как функция, которую вы написали, может быть написан как List<Integer> increment(List<Integer> input). Тело метода Java, вероятно, итерацию по списку элемент в то время, и установить каждый элемент сам по себе плюс один:

List<Integer> increment(List<Integer> input) { 
    for (int i = 0; i < input.size; i++) { 
     input.set(i, input.get(i) + 1); 
    } 
} 

Erlang не имеет почти ничего общего с этим. Начнем с того, что «подпись» функции erlang - это имя и арность функции. Arity означает, сколько аргументов принимает функция. Таким образом, ваша инкрементная функция известна как increment/1, и это ее уникальная подпись. То, как вы пишете список аргументов внутри круглых скобок после имени функции, меньше относится к типам аргументов, чем к шаблону данных, переданных ему. Функция, подобная increment([]) -> ..., может быть успешно вызвана, передав ее [], пустой список. Аналогично, функция increment([Item]) -> ... может быть успешно вызвана путем передачи ей списка с одним элементом в нем, а increment([Item1, Item2]) -> ... должен быть передан список с двумя элементами в нем. Эта концепция сопоставления данных с шаблонами довольно точно известна как «сопоставление образцов», и вы найдете ее на многих функциональных языках. В функциях Erlang используется для выбора того, какую головку функции выполнить. Это имеет грубое сходство с перегрузкой метода Java, где у вас может быть множество методов с тем же именем, но с разными типами аргументов; однако шаблон в голове функции Erlang может связывать переменные с разными частями аргументов, соответствующих шаблону.

В вашем примере кода функция increment/1 имеет две головки. Первая глава выполняется только в том случае, если вы передаете пустой список функции. Вторая глава выполняется только в том случае, если вы передаете непустой список функции. Когда это произойдет, две переменные, H и T, связаны. H привязан к первому элементу списка, а T привязан к остальной части списка, что означает все, кроме первого элемента. Это потому, что шаблон [H|T] соответствует непустому списку, включая список с одним элементом, и в этом случае T будет связан с пустым списком. Связанные таким образом переменные могут быть использованы в теле функции.

Тела ваших функций - очень типичная форма итерации списка в Эрланге для создания нового списка. Это типично из-за другого важного отличия от Java, которое заключается в том, что данные Erlang неизменяемы. Это означает, что нет такой концепции, как «установка элемента списка», как это было в приведенном выше коде Java. Если вы хотите изменить список, вам нужно создать новый, что и делает ваш код. Он эффективно говорит:

  • Результатом увеличения пустого списка является пустой список.
  • Результат приращения непустого списка является:
    • Возьмите первый элемент списка: H.
    • Возрастайте со списком: increment(T).
    • Подготовить H+1 к результату увеличения остальной части списка.

Обратите внимание, что вы хотите быть осторожным о том, как строить списки в Erlang, или вы можете в конечном итоге тратить много ресурсов. List Handling User's Guide - хорошее место, чтобы узнать об этом. Также обратите внимание, что в этом коде используется концепция, называемая «рекурсия», что означает, что функция вызывает себя. На многих популярных языках, включая Java, рекурсия имеет ограниченную полезность, поскольку каждый вызов новой функции добавляет фрейм стека, а доступное пространство памяти для фреймов стека относительно ограничено. Эрланг и многие функциональные языки поддерживают вещь, известную как «устранение хвоста», которая является функцией, которая позволяет правильно написанный код повторно обрабатывать без исчерпания ресурсов.

Надеюсь, это поможет объяснить ситуацию. Если вы можете задать более конкретный вопрос, вы можете получить лучший ответ.

Смежные вопросы