Вложенные функции: Неправильное использование побочных эффектов?

Вы также можете использовать это. Отметьте Building как класс вместо Buildings. Отделите здания от города и внедрите их с помощью конструктора:

Кроме того, ваш int i = 0; i++ имеет ошибки и может вызвать IndexOutOfRangeException .

public class Town
{
    private List<Building> buildings;
    private List<string> buildingNames = new List<string>() {"Town_Hall", "Market", "Residences", "Mortician", "Bank", "Hotel", "Tailor", "Gunsmith", "General_Store", "Sheriff", "Well", "Gate", "Wall"};

    public Town(List<Building> buildings)
    {
       this.buildings = buildings;
    }

    public void ResetTown()
    {
        int i = 0;
        foreach (Building building in buildings)
        {
            building.Name = buildingNames[i].ToString();
            building.Level = 0;
            i++;
        }
    }

    public IEnumerator<Building> GetEnumerator() 
    { 
        return buildings.GetEnumerator(); 
    } 
}

public class Building
{
    public string Name {get; set;}
    public int Level {get; set;}
}
6
задан J Cooper 22 November 2008 в 06:40
поделиться

3 ответа

Вложенные функции являются отличным способом разделить работу на многие функции. Это не действительно "сторона-effecty"; если это помогает, думайте о полученных переменных как о неявных параметрах.

Один пример, где вложенные функции полезны, состоит в том, чтобы заменить циклы. Параметры к вложенной функции могут действовать как индукционные переменные, которые накапливают значения. Простой пример:

let factorial n =
    let rec facHelper p n =
        if n = 1 then p else facHelper (p*n) (n-1)
    in
    facHelper 1 n

В этом случае действительно не имело бы смысла объявлять функцию как facHelper глобально, так как пользователям не придется волноваться о p параметр.

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

3
ответ дан 16 December 2019 в 21:47
поделиться

Функциональное программирование не является бескомпромиссным. Если бы вложение, функции имеют больше смысла, я пошел бы с тем подходом. Однако, Если Вы действительно хотите, чтобы внутренние функции были чисто функциональны, явно передайте все необходимые параметры в них.

Вот немного примера в Схеме:

(define (foo a)
  (define (bar b)
    (+ a b))      ; getting a from outer scope, not purely functional
  (bar 3))

(define (foo a)
  (define (bar a b)
    (+ a b))      ; getting a from function parameters, purely functional
  (bar a 3))


(define (bar a b) ; since this is purely functional, we can remove it from its
  (+ a b))        ; environment and it still works

(define (foo a)
  (bar a 3))

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

4
ответ дан 16 December 2019 в 21:47
поделиться

Рассмотрите следующий (изобретенный) отрывок Haskell:

putLines :: [String] -> IO ()
putLines lines = putStr string
    where string = concat lines

string локально связанная именованная константа. Но не это также функция, берущая аргументы, который закрывается lines и поэтому соотносимо intransparent? (В Haskell константы и функции nullary действительно неразличимы!) Вы считали бы вышеупомянутый код “стороной-effecty” или нефункциональный из-за этого?

1
ответ дан 16 December 2019 в 21:47
поделиться
Другие вопросы по тегам:

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