Какую функцию я могу поместить как НЕЧТО здесь для получения верный в конце? Я играл с установленным на хеш (только корректный для первых 2 значений), союз и concat, но я знаю, что не обрабатываю одноэлементное по сравнению с установленным условием правильно только с ни одним из тех.
(defn mergeMatches [propertyMapList]
"Take a list of maps and merges them combining values into a set"
(reduce #(merge-with FOO %1 %2) {} propertyMapList))
(def in
(list
{:a 1}
{:a 2}
{:a 3}
{:b 4}
{:b 5}
{:b 6} ))
(def out
{ :a #{ 1 2 3}
:b #{ 4 5 6} })
; this should return true
(= (mergeMatches in) out)
Что самый идиоматический путь состоит в том, чтобы обработать это?
Это подойдет:
(let [set #(if (set? %) % #{%})]
#(clojure.set/union (set %) (set %2)))
Перепишите более прямо для примера (Алекс):
(defn to-set [s]
(if (set? s) s #{s}))
(defn set-union [s1 s2]
(clojure.set/union (to-set s1) (to-set s2)))
(defn mergeMatches [propertyMapList]
(reduce #(merge-with set-union %1 %2) {} propertyMapList))
Другое решение, предложенное @wmacgyver в Twitter на основе мультиотображений :
(defn add
"Adds key-value pairs the multimap."
([mm k v]
(assoc mm k (conj (get mm k #{}) v)))
([mm k v & kvs]
(apply add (add mm k v) kvs)))
(defn mm-merge
"Merges the multimaps, taking the union of values."
[& mms]
(apply (partial merge-with union) mms))
(defn mergeMatches [property-map-list]
(reduce mm-merge (map #(add {} (key (first %)) (val (first %))) property-map-list)))
Кажется, это работает:
(defn FOO [v1 v2]
(if (set? v1)
(apply hash-set v2 v1)
(hash-set v1 v2)))
«Неизменяемая замена образца стиля JavaBean» может выражаться именованными параметрами и при необходимости аннотацией @ BeanProperty:
import reflect._
case class A(@BeanProperty val x: String, @BeanProperty val y : Int)
A(x = "s", y = 3)
A(y = 3, x = "s")
Добавление методов (точнее: определение нового интерфейса) имеет смысл только в статически типизированном языке, если клиент знает о новых методах и может компилировать их по интерфейсу. С помощью структурного типирования клиенты могут определять методы, которые, как ожидается, будут присутствовать в объекте. Компилятор Scala преобразует структурный тип в код отражения, который может завершиться сбоем во время выполнения.
type T = {def go(x : Int): Int }
def y(any : Any) = any.asInstanceOf[T].go(2)
class A{
def go(x : Int) = x + 1
}
y(new A())
y(new {}) //this will fail
Новые классы или признаки можно определить с помощью интерпретатора на лету. Метод Interpret преобразует код Scala в байтовый код.
Вы уже упомянули о ScalaSigParser , с которым непросто работать.
Я думаю, что остальных функций, которые вам нравятся, еще нет.
-121--2863490-Я не вижу ничего плохого в этом подходе. Этот метод можно найти под разными именами в целом ряде рамок, например StartMessenger в Zend Framework . Обычно сеанс переносится в объект вместо обычного массива сеанса и с помощью ViewHelper вместо функции.
Чтобы убедиться в отсутствии опечаток в клавишах сеанса при назначении сообщения, можно также преобразовать код назначения в функцию, например,
function set_message($text, $type)
{
$_SESSION['message'] = array(
'text' => $text,
'type' => $type
);
}
Вы можете улучшить его, если функция возвращает последовательности вместо эхо
, и лично я использую sprintf
для форматирования вывода. Делает код несколько более читаемым imho, например
return sprintf('<div id="message-box" class="type-%s">%s</div>',
$_SESSION["message"]["text"],
$_SESSION["message"]["type"]);
Как отметил @ Gumbo, функция может не работать, когда Сеансы не работают, но это, вероятно, наложит ряд других проблем для всего приложения тогда, так что я бы точно не беспокоился об этой конкретной части кода тогда.
Незначительная вещь: $ _ SESSION является сверхглобальным , поэтому не нужно использовать ключевое слово global
.
Не супер красиво, но это работает.
(defn mergeMatches [propertyMapList]
(for [k (set (for [pp propertyMapList] (key (first pp))))]
{k (set (remove nil? (for [pp propertyMapList] (k pp))))}))
Я этого не писал, но это был вклад от @амитратуры в Twitter:
(defn kv [bag [k v]]
(update-in bag [k] conj v))
(defn mergeMatches [propertyMapList]
(reduce #(reduce kv %1 %2) {} propertyMapList))
Я бы не стал использовать merge - для этого
(defn fnil [f not-found]
(fn [x y] (f (if (nil? x) not-found x) y)))
(defn conj-in [m map-entry]
(update-in m [(key map-entry)] (fnil conj #{}) (val map-entry)))
(defn merge-matches [property-map-list]
(reduce conj-in {} (apply concat property-map-list)))
user=> (merge-matches in)
{:b #{4 5 6}, :a #{1 2 3}}
fnil скоро станет частью ядра, так что вы можете игнорировать реализацию... но она просто создает версию другой функции, которая может обрабатывать нулевые аргументы. В этом случае конъюнктура заменит #{} на nil.
Таким образом, сокращение, соединяющее с множеством для каждого ключа/значения в списке поставляемых карт.