Взаимная рекурсия — может кто-то помогать объяснить, как этот код работает?

В соответствии с моим пониманием Продукты, основанные на геолокации WooCommerce

Этот плагин / расширение WooCommerce, который добавляет в ваш магазин возможность показывать / скрывать продукты на основе геолокации посетителей.

Вы можете добавить много разных стран, в которых вы хотите применить настройки. Вы делаете это, добавляя правило и устанавливая двухбуквенный код страны ISO, к которому вы хотите обратиться. Например, «США». Затем вы можете установить, какие продукты и категории показывать / скрывать. Вы можете выбрать более одного для каждого правила.

Вы также можете добавить регион или фильтр по городам.

5
задан J Cooper 29 December 2008 в 08:44
поделиться

5 ответов

Я нахожу, что обычно стоит разработать поведение маленьких программ Haskell вручную. Правила оценки довольно просты. Ключевая вещь помнить состоит в том, что Haskell нестрог (иначе ленивый): выражения оценены только при необходимости. Лень является причиной, на вид бесконечные определения могут привести к полезным результатам. В этом случае, использование take средства нам только будут нужны первые 10 элементов бесконечного списка reqs: они - все, в чем мы "нуждаемся".

На практике "потребность" обычно управляется соответствиями шаблона. Например, выражение списка будет обычно оцениваться до такой степени, когда, мы можем различать [] и (x:xs) перед функциональным приложением. (Обратите внимание что'~'предшествуя шаблону, как в определении client, делает это ленивым (или неопровержимый): ленивый шаблон не вызовет свой аргумент, пока целое выражение не будет вызвано.)

Запоминание этого take :

take 0 _      = []
take n (x:xs) = x : take (n-1) xs

Оценка take 10 reqs похож:

take 10 reqs 
      -- definition of reqs
    = take 10 (client initial resps)
      -- definition of client [Note: the pattern match is lazy]
    = take 10 (initial : (\ resp:resps' -> client (next resp) resps') 
                             resps)
      -- definition of take
    = initial : take 9 ((\ resp:resps' -> client (next resp) resps') 
                            resps)
      -- definition of initial
    = 0 : take 9 ((\ resp:resps' -> client (next resp) resps') 
                      resps)
      -- definition of resps
    = 0 : take 9 ((\ resp:resps' -> client (next resp) resps') 
                      (server reqs))
      -- definition of reqs
    = 0 : take 9 ((\ resp:resps' -> client (next resp) resps') 
                      (server (client initial resps)))
      -- definition of client
    = 0 : take 9 ((\ resp:resps' -> client (next resp) resps') 
                      (server (initial : {- elided... -}))
      -- definition of server
    = 0 : take 9 ((\ resp:resps' -> client (next resp) resps') 
                      (process initial : server {-...-}))
      -- beta reduction 
    = 0 : take 9 (client (next (process initial)) (server {-...-})
      -- definition of client 
    = 0 : take 9 (next (process initial) : {-...-})
      -- definition of take 
    = 0 : next (process initial) : take 8 {-...-}
      -- definition of next 
    = 0 : process initial : take 8 {-...-}
      -- definition of process 
    = 0 : initial+1 : take 8 {-...-}
      -- definition of initial 
    = 0 : 1 : take 8 {-...-}
      -- and so on...
12
ответ дан 18 December 2019 в 05:50
поделиться

Это было некоторое время, так как я играл с Haskell, но я вполне уверен, что это лениво оценено, означая, что это только вычисляет то, в чем это на самом деле нуждается. Таким образом, в то время как reqs является бесконечно рекурсивным с тех пор take 10 reqs только нуждается в первых 10 элементах возвращенного списка, который является всем, что на самом деле вычисляется.

4
ответ дан 18 December 2019 в 05:50
поделиться

Понимание этого кода требует двух навыков:

  • различение 'определения', которое может быть бесконечным (как набор натуральных чисел: naturals = (1 : map '\n->n+1' naturals), или список обработанных запросов) и 'сокращение', которое является процессом отображения фактических данных к этим определениям
  • наблюдение структуры этого клиент-серверного приложения: это - просто пара процессов, говорящих друг с другом: 'клиент-сервер' дурная слава, действительно: это нужно было назвать 'wallace-кольцом' или 'панелью нечто' или говорящими философами или что бы то ни было, но это симметрично: эти две стороны являются коллегами.

Поскольку Jon уже заявил, работы сокращения ленивым способом (иначе 'вызов по необходимости'): take 2 naturals сначала не оценил бы полный набор naturals, но просто взял бы первый и предварительно ожидал бы это к take 1 (map '\n->n+1' naturals), который уменьшил бы до [1, (1+1)] = [1,2].

Теперь структура клиент-серверного приложения - это (к моему глазу):

  • server путь состоит в том, чтобы создать список ответов из списка запросов при помощи process функция
  • client путь состоит в том, чтобы создать запрос на основе ответа и добавить ответ того запроса к списку ответов.

Если Вы смотрите тесно, Вы видите, что оба - 'способ создать x:xs из y:ys'. Таким образом, мы могли равномерно назвать их wallace и gromit.

Теперь было бы легко понять если client был бы назван только с списком ответов:

someresponses = wallace 0 [1,8,9]    -- would reduce to 0,1,8,9
tworesponses  = take 2 someresponses -- [0,1]

Если ответы не буквально известны, но производятся gromit, мы можем сказать

gromitsfirstgrunt = 0
otherresponses = wallace gromitsfirstgrunt (gromit otherresponses)
twootherresponses = take 2 otherresponses -- reduces to [0, take 1 (wallace (gromit ( (next 0):...) )]
                                          -- reduces to [0, take 1 (wallace (gromit ( 0:... ) )  ) ]
                                          -- reduces to [0, take 1 (wallace (1: gromit (...)  )  ) ]
                                          -- reduces to [0, take 1 (1 : wallace (gromit (...)  ) ) ]
                                          -- reduces to [0, 1 ]

Один из обоих коллег должен 'запустить' обсуждение, следовательно начальное значение, предоставленное wallace.

Также отметьте ~ перед шаблоном gromit: это говорит Haskell, что содержание аргумента списка не должно быть уменьшено - если он видит, что это - список, это достаточно. Существует хорошая тема на этом в wikibook на Haskell (ищите "Ленивое Сопоставление с образцом).

11
ответ дан 18 December 2019 в 05:50
поделиться

См. также мой ответ на вопрос о Том, "чтобы жениться" здесь

2
ответ дан 18 December 2019 в 05:50
поделиться

Это похоже на хорошую путаницу. Если Вы читаете точно, Вы нашли это простым:

далее? это - идентификационные данные

сервер? это - просто процесс карты, который является картой '\n-> n+1'

клиент? Это - неясный путь, как записать 0: клиент сервера, например, 0: отобразите '\n-> n+1' [0: отобразите '\n-> n+1' [0:...]]

0
ответ дан 18 December 2019 в 05:50
поделиться
Другие вопросы по тегам:

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