Пояснение значения параметра

Этот вопрос напрямую связан с StackOverFlow при подсчете цифр . Я поднял решение этого вопроса, и у меня есть два вопроса:

Сначала вот решение:

(defn num-digits-tail-recursion 
        ([n count]
           (if (= 0 n)
             count
             (recur (quot n 10) (inc count))))
        ([n] (num-digits-tail-recursion n 0)))
  1. count — это отдельная функция для подсчета количества символов в строке. Правильно ли я предполагаю, что count разрешен как var, потому что он не находится в первой позиции списка?

  2. count — это второй параметр, но я передаю только один параметр — число. Что особенного в синтаксисе функции, который начинается со списка, а не типичного вектора параметров (defn test_fn [x y] (println x))?

Редактировать:

Прошу прощения за неясность в исходном вопросе. Почему предоставление имени функции -- count -- не приводит к тому, что num-digits-tail-recursion ожидает второго параметра? Если я поставлю ([n x]... вместо (n count]... и вызову функцию с одним аргументом, я получу ошибку insuf arguments.


person octopusgrabbus    schedule 26.10.2011    source источник


Ответы (2)


Вопрос № 1: Clojure имеет лексическую область видимости. поэтому, если вы создаете локальную переменную с тем же именем, что и переменная, определенная в охватывающей области, локальная копия будет «затенять» внешнюю. В этом случае count из clojure.core является внешней областью видимости, а count из этой функции закрывает ее. когда вы ссылаетесь на count внутри этой функции, вы видите определение из списка аргументов локальных функций.

(def x 4)
(defn foo [x]
    (println x))
(foo 42)
=> 42

в вашем конкретном случае count определяется в другом пространстве имен, хотя концепция области видимости такая же.

пример части 2:

(defn foo
  ([] (println "i have no args"))
  ([x] (println "i have one arg " x))
  ([x y] (println "i have two args " x " " y)))
person Arthur Ulfeldt    schedule 26.10.2011
comment
Ответ Мишеля на вторую часть хорошо это объясняет. Я отредактирую, чтобы добавить пример кода. Проверьте его ответ по ссылке - person Arthur Ulfeldt; 27.10.2011
comment
Итак, вы думаете, что count использовался для второго параметра рекурсии без необходимости его предоставления при вызове внешней функции? - person octopusgrabbus; 27.10.2011

  1. Именование аргументов, которые несут функции так же, как и существующие функции из пространства имен, на которые ссылаются, не является хорошей идеей, хотя в вашем примере здесь count не используется таким образом. В вашем примере count — это просто int, который увеличивается на каждой рекурсивной итерации!

    Но если вы хотите передать функцию подсчета и называете аргумент, который используется для нее, «подсчетом», какая функция будет вызвана? Функция clojure.core/count или переданная функция? (исправление: переданная функция из-за лексической области видимости). Поэтому избегайте путаницы и выберите другое имя. Даже если вы не передаете функции, лучше избегать этих имен.

  2. Функции поддерживают перегрузку арности, и это то, что вы сейчас используете. Просто прочитайте это: http://clojure.org/functional_programming

person Michiel Borkent    schedule 26.10.2011
comment
Я немного запутался в том, чтобы изменить количество имен, где и как будет называться счет. - person octopusgrabbus; 26.10.2011
comment
@octopusgrabbus Михиль говорит, что если вы назовете аргумент, который принимает функцию count, вы обнаружите, что вызов count вызовет основную функцию, а не вашу функцию. В вашем коде count - это просто int, поэтому этой проблемы не возникает. - person Adrian Mouat; 26.10.2011
comment
Однако это неверно — если вы привязываете локальный объект с именем count, будь то в качестве аргумента функции или в привязке let, а затем вызываете этот локальный объект как функцию, clojure.core/count вообще не участвует — вместо этого вызывается ваша функция. - person amalloy; 27.10.2011
comment
Но я все еще в замешательстве. Если я могу указать функцию (count) в качестве второго параметра, потому что поддерживается перегрузка функций, то как count используется внутри функции, даже если я использую другую переменную для отслеживания счетчика? - person octopusgrabbus; 27.10.2011
comment
В этом случае вам не нужно передавать функцию для подсчета, потому что подсчет выполняется путем inc-повторения счетчика value на каждой итерации. - person Michiel Borkent; 27.10.2011