Тестирование функции высшего порядка, которая компилирует структуры в функциональные списки - PullRequest
0 голосов
/ 18 декабря 2010

У меня есть такая карта (которая может быть вложена, используя обычные логические операторы, используя модуль «логический» и «данные» будут содержать соответствующие значения, такие как «влево», «вправо» и «оператор» будет "и", "или", "не"):

{ "data"   { "name" "lang", "operator" "=", "value" "blue" },
  "module" "impression_hint"}

Что мне нужно, так это функция, которая возвращает список, который можно интерполировать в (fn [context] ...) списке, где он сможет выполнять то, что мы к нему добавим.

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

(fn [context]
    (= ((context :impression_hint) "lang") "blue"))

Таким образом, моя функция синтаксического анализа / компиляции должна возвращать только часть (= ...). У меня есть нечто, что мучительно близко:

(defn- parse-internal [tree acc]
  (cond
    ; other cases will go here

    (= "impression_hint" (tree "module"))
    (let [data  (tree "data")
          op    (data "operator")
          name  (data "name")
          value (data "value")]
      `(~(symbol op) ((context :impression_hint) ~name) ~value))

    :else
    (throw (RuntimeException. (str "Unknown module: " (tree "module"))))))

В моем тесте это возвращает:

FAIL in (simple-shallow-rules-generate-simple-shallow-functions) (targeting.clj:10)
expected: (= (quote (= ((context :impression_hint) "name") "blue")) (bloom.adgear.targeting/parse {"data" {"name" "lang", "operator" "=", "value" "blue"}, "module" "impression_hint"}))
  actual: (not (= (= ((context :impression_hint) "lang") "blue")
                  (= ((bloom.adgear.targeting/context :impression_hint) "lang") "blue")))

Обратите внимание на параметр контекста? Это было пространство имен, и это делает мой тест неудачным. Я уверен, что могу что-то сделать, но вызов символа приводит к тому, что символ не определен, что имеет смысл, поскольку символ еще не существует.

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

1 Ответ

1 голос
/ 19 декабря 2010

Проблема состоит в том, что буквенные символы без пространства имён в формах с синтаксическими кавычками (с предшествующим обратным тэгом) заполняются компонентом пространства имен на основе того, где форма с синтаксическими кавычками появляется лексически.Ваш файл может появиться в файле, где определено пространство имен bloom.adgear.targeting, так что именно это и прикрепляется к context.

В большинстве случаев это крутая функция, но когда вам нужно избегатьэто, вы можете использовать трюк ~':

`foo
; => some-ns/foo
`~'foo
; => foo

Тильда снимает кавычки на следующей форме, поэтому на нее не влияет магия синтаксической кавычки (включая символы авторазрешения);но затем он оценивается, поэтому необходима кавычка, чтобы вы вернули исходную форму (символ foo), а не ее значение (независимо от того, к чему foo привязан в настоящее время).

...