Add more comments to Clojure version. Send error messages to stderr. Print command line to log file. Only init file logging if the log file is specified on the command line

--- clojure/src/biotool/core.clj
+++ clojure/src/biotool/core.clj
@@ -1,7 +1,7 @@
 ;;; Module:      biotool.core
 ;;; Description: Reads one or more FASTA files and computes various
 ;;;              simple statistics about them. Intended as an example
-;;;              bioinformatics command line tool
+;;;              bioinformatics command line tool.
 ;;; Copyright:   (c) Bernie Pope, 2017
 ;;; License:     MIT
 ;;; Maintainer:  bjpope@unimelb.edu.au
@@ -10,7 +10,7 @@

 ;;; The main parts of the program are:
 ;;; 1. Parse command line arguments.
-;;; 2. Process each FASTA file in sequence
+;;; 2. Process each FASTA file in sequence.
 ;;; 3. Pretty print output for each file.
 ;;;
 ;;; If no FASTA filenames are specified on the command line then the program
@@ -32,6 +32,8 @@
   "Initial value of stats, before any sequences have been considered"
   {:num-sequences 0
    :num-bases 0
+   ;; We set the min and max sequence lengths to nil, indicating that
+   ;; we have not seen any sequences yet.
    :min-sequence-length nil
    :max-sequence-length nil})

@@ -136,28 +138,72 @@
                    (bs/biosequence-seq reader)))))

 (defn process-fasta-file
+  "Compute the statistics for a single input FASTA file from a file, given by its filename,
+  and pretty print the result to the standard output. It is a wrapper around
+  process-fasta-reader.
+
+  Arguments:
+    minlen: The minimum length sequence allowed (non-negative int). Sequences shorter than
+      this will be skipped by the program.
+    filename: The name of the FASTA file to process.
+
+  Result:
+    nil"
+
   [minlen filename]
   (timbre/info "Processing FASTA file from" filename)
   (with-open [reader (bs/bs-reader (bs/init-fasta-file filename :iupacAminoAcids))]
     (process-fasta-reader minlen filename reader)))

 (defn process-stdin
+  "Compute the statistics for a single input FASTA file from stdin,
+  and pretty print the result to the standard output. It is a wrapper around
+  process-fasta-reader.
+
+  Arguments:
+    minlen: The minimum length sequence allowed (non-negative int). Sequences shorter than
+      this will be skipped by the program.
+
+  Result:
+    nil"
   [minlen]
   (timbre/info "Processing FASTA file from stdin")
   (with-open [reader (bs/init-fasta-reader (java.io.BufferedReader. *in*) :iupacAminoAcids)]
     (process-fasta-reader minlen "stdin" reader)))

-(def header "FILENAME\tTOTAL\tNUMSEQ\tMIN\tAVG\tMAX")
-
 (defn process-fasta-files
+  "Compute the statistics for each file in an array of filenames. If the array is
+  empty, compute statistics from stdin. Print an output header before any inputs
+  are processed.
+
+  Arguments:
+    minlen: The minimum length sequence allowed (non-negative int). Sequences shorter than
+      this will be skipped by the program.
+
+    files: A possibly empty array of filenames (array of strings).
+
+  Result:
+    nil"
   [minlen files]
-  (println header)
-  (if (empty? files)
-    (process-stdin minlen)
-    (doseq [file files]
-      (process-fasta-file minlen file))))
-
-(defn usage [options-summary]
+  (let [header "FILENAME\tTOTAL\tNUMSEQ\tMIN\tAVG\tMAX"]
+    (println header)
+    (if (empty? files)
+      ;; If there are no filenames to process, then use stdin.
+      (process-stdin minlen)
+      ;; Otherwise process each file in sequence.
+      (doseq [file files]
+        (process-fasta-file minlen file)))))
+
+(defn usage
+  "Print usage information for the program
+
+  Arguments:
+    options-summary: A summary of the available program options (string).
+
+  Result:
+    nil"
+
+  [options-summary]
   (->> ["Print fasta stats"
         ""
         "Usage: program-name [options] FILES"
@@ -166,31 +212,64 @@
         options-summary]
        (string/join \newline)))

-(defn error-msg [errors]
+(defn error-msg
+  "Display a message about command line errors.
+
+   Arguments:
+     errors: The command line errors that occurred (array of string).
+
+   Result:
+     nil
+  "
+  [errors]
   (str "The following errors occurred while parsing your command:\n\n"
        (string/join \newline errors)))

-(defn exit [status msg]
-  (println msg)
+(defn exit
+  "Print an error message to stderr and then exit the program
+  with a given exit status.
+
+  Arguments:
+    status: The exit status of the program (non-negative integer).
+    msg: Error message to display on stderr (string).
+
+  Result:
+    nil"
+  [status msg]
+  (binding [*out* *err*] println msg)
   (System/exit status))

-(def default-minlen 0)
-
 (def cli-options
-  [[nil "--minlen N" "Minimum length sequence to include in stats"
-    :default default-minlen :parse-fn #(Integer/parseInt %)]
-   [nil "--log LOG-FILE" "record program progress in LOG-FILE"]
-   ["-v" "--version"]
-   ["-h" "--help"]])
-
-(defn config-logging
+  "Define the command line options of the program."
+  (let [default-minlen 0]
+    [[nil "--minlen N" "Minimum length sequence to include in stats"
+      :default default-minlen :parse-fn #(Integer/parseInt %)]
+     [nil "--log LOG-FILE" "record program progress in LOG-FILE"]
+     ["-v" "--version"]
+     ["-h" "--help"]]))
+
+(defn init-logging
+  "Initialise program logging if a log-filename has been specified, and also log
+  a message indicating that the program has started. Log messages are configured to
+  be written to the specified log file.
+
+  Arguments:
+    log-filename: Either a string indicating the name of the log file, or nil indicating
+      that no logging should happen
+
+  Result:
+    nil"
   [log-filename]
+  ;; Turn off the default logging to stdout.
+  (timbre/merge-config! {:appenders {:println {:enabled? false}}})
   (when log-filename
-    (let [log-file-name log-filename]
-      (timbre/merge-config! {:appenders {:println {:enabled? false}}})
+      ;; Enable log messages to be written to the specified log file.
       (timbre/merge-config! {:appenders {:spit (appenders/spit-appender {:fname log-filename})}})
+      ;; Set the minimum log level to "info"
       (timbre/set-level! :info))
-    (timbre/info "Program started")))
+    ;; Write a log message indicating that the program has started.
+    (timbre/info "Program started")
+    (timbre/info "Command line: " (string/join " " *command-line-args*)))

 (defn -main
   "Orchestrate the computation"
@@ -199,5 +278,5 @@
     (cond
       (:help options) (exit 0 (usage summary))
       errors (exit 1 (error-msg errors)))
-    (config-logging (:log options))
+    (init-logging (:log options))
     (process-fasta-files (:minlen options) arguments)))


Coerce Joda Time to java.util.Date

Coerce Joda Time to java.util.Date

--- src/checkin_halake/routes/admin.clj
+++ src/checkin_halake/routes/admin.clj
@@ -10,12 +10,13 @@
              [checkin :as checkin]]
             [clj-time
              [format :as format]
-             [local :as local]]))
+             [local :as local]
+             [coerce :as coerce]]))

 (def format (format/formatter "yyyy-MM-dd HH:mm"))

 (defn- str->datetime [s]
-  (local/to-local-date-time (format/parse format s)))
+  (coerce/to-date (local/to-local-date-time (format/parse format s))))

 (defroutes ^:private admin-routes*
   (POST "/users" {{:keys [name password phone email]} :params}


Check msg meta to determine sendmail or SMTP.

--- src/clj/com/draines/postal/core.clj
+++ src/clj/com/draines/postal/core.clj
@@ -8,7 +8,7 @@
                  (:subject msg)
                  (:body msg))
     (throw (Exception. "message needs at least :from, :to, :subject, and :body")))
-  (if (:host msg)
+  (if (:host ^msg)
     (smtp-send msg)
     (sendmail-send msg)))


Add yoy-change

Add yoy-change

--- src/clj_simple_chart/data/utils.clj
+++ src/clj_simple_chart/data/utils.clj
@@ -64,4 +64,16 @@
           (reduce (fn [o [k v]]
                     (if (not (some #{k} columns))
                       o
-                      (assoc o k v))) {} x)) data))+                      (assoc o k v))) {} x)) data))
+
+(defn yoy-change [rows]
+  (map-indexed (fn [idx x]
+                 (reduce (fn [o [k v]]
+                           (cond (number? v) (assoc o k (- v (get (nth rows idx) k)))
+                                 :else (assoc o k v)))
+                         {} x))
+               (rest rows)))
+
+(test/is (= (yoy-change [{:year "2000" :v 10}
+                         {:year "2001" :v 15}])
+            [{:year "2001" :v 5}]))


continue fleshing out commodities page

continue fleshing out commodities page

--- src/cljs/clj_money/commodities.cljs
+++ src/cljs/clj_money/commodities.cljs
@@ -7,7 +7,9 @@
             [clj-money.notifications :as notify]
             [clj-money.dom :refer [app-element]]
             [clj-money.layout :refer [with-layout]]
+            [clj-money.util :as util]
             [clj-money.forms :refer [text-input
+                                     select-input
                                      required]]))

 (defn- commodity-row
@@ -34,11 +36,39 @@
         (for [commodity @commodities]
           (commodity-row commodity))]])))

-(defn commodities-page []
+(defn- commodities-page []
   (with-layout
     [:section
-       [:h1 "Commodities"]
-       [commodity-list]]))
+     [:h1 "Commodities"]
+     [commodity-list]
+     (util/add-button "/commodities/new")]))
+
+(defn- create-commodity
+  [commodity]
+  (.log js/console "create commodity " (prn-str commodity)))
+
+(def ^:private commodity-form
+  [:form
+   (select-input :type ["currency" "stock"])
+   (select-input :exchange ["nyse" "nasdaq"] {:visible? #(= (:type %) "stock")})
+   (text-input :symbol :required)
+   (text-input :name :required)])
+
+(defn- new-commodity []
+  (let [commodity (r/atom {})]
+  (with-layout
+    [:div.row
+     [:div.col-md-6
+     [:h1 "New Commodity"]
+     [bind-fields commodity-form commodity]
+     (util/button "Save" #(create-commodity @commodity) {:class "btn btn-primary"
+                                                         :icon :ok})
+     (util/space)
+     (util/link-to "Cancel" "/commodities" {:class "btn btn-danger"
+                                            :icon :ban-circle})]])))
+
+(secretary/defroute "/commodities/new" []
+  (r/render [new-commodity] (app-element)))

 (secretary/defroute "/commodities" []
   (r/render [commodities-page] (app-element)))


Change Vote for US to Vote for ICMers

Change Vote for US to Vote for ICMers

--- src/cljs/ikea_clojure_cup/core.cljs
+++ src/cljs/ikea_clojure_cup/core.cljs
@@ -53,7 +53,7 @@
                               :on-click #(swap! regions/region-state dissoc :region)}
           (str "Region: " (get-in @regions/region-state [:region :name]))]
          [bootstrap/nav-item {:title "About" :href "/about"} "About"]
-         [bootstrap/nav-item {:title "Vote for Us" :target "_blank" :href "http://clojurecup.com/teams/"} [bootstrap/glyph {:glyph :thumbs-up}] " Vote for Us"]
+         [bootstrap/nav-item {:title "Vote for ICMers" :target "_blank" :href "http://clojurecup.com/teams/"} [bootstrap/glyph {:glyph :thumbs-up}] " Vote for Us"]
          [bootstrap/nav-item {:title "Start over" :bs-style :danger
                               :href "/"
                               :on-click tool/start-over} "Start over"]]]])))


welcome note

welcome note

--- src/cljs/ikea_clojure_cup/tool.cljs
+++ src/cljs/ikea_clojure_cup/tool.cljs
@@ -51,8 +51,11 @@
                         :role "alert"
                         :on-click #(swap! tool-state assoc :shown-intro? true)}
       [:span {:aria-hidden true} "⨉"]]
-     [:p [:strong "Welcome!"]
-      " Quod satis pecuniae sempiternum. Ut sciat oportet motum. Nunquam invenies eum. Hic de tabula. Ego vivere, ut debui, et nunc fiant. Istuc quod opus non est. Lorem ipsum occurrebat pragmaticam semper ut, si quis ita velim tibi bene recognoscere. Quorum duo te mihi videtur. Mauris a nunc occideritis me rectum. Videtur quod Ive facillimum, qui fecit vos. Potes me interficere, sine testibus et tunc manere in pauci weeks vel mensis vestigia Isai Pinkman et vos quoque illum occidere. Exercitium inutili option A. Videtur mihi quod autem est."]]))
+     [:p
+      "Don't you hate it when you reach your car with all your recently purchased IKEA goodies only to realise they don't fit!
+You then proceed to play IKEA-car-boot Tetris and often end up opening all the boxes in order to get the contents in.
+Well those days are over thanks to IFLOGS, the IKEA Fleet Logistics System!
+Simply select the items you wish to purchase and tell us the dimensions of your car boot and we'll let you know if it fits AND how to get it in (no more Tetris!)."]]))

 (defn tool-view
   []


open issuer modal

open issuer modal

--- src/cljs/salava/badge/ui/stats.cljs
+++ src/cljs/salava/badge/ui/stats.cljs
@@ -80,9 +80,9 @@
      (if (= @visible-area-atom panel-identity)
        (into [:div.panel-body]
              (for [issuer issuers
-                   :let [{:keys [issuer_content_name issuer_content_url badges]} issuer]]
+                   :let [{:keys [issuer_content_id issuer_content_name issuer_content_url badges]} issuer]]
                [:div.issuer-badges-wrapper
-                [:h4 [:a {:href issuer_content_url :target "_blank"} issuer_content_name] ": " (count badges)]
+                [:h4 [:a {:href "#" :on-click #(mo/open-modal [:badge :issuer] issuer_content_id)} issuer_content_name] ": " (count badges)]
                 (into [:div.issuer-badges]
                       (for [badge badges
                             :let [{:keys [id image_file name]} badge]]


[search] Fix coming to search page via link not setting bar text

--- src/braid/search/ui/search_bar.cljs
+++ src/braid/search/ui/search_bar.cljs
@@ -11,8 +11,9 @@
                prev-page (r/atom (:type @(subscribe [:page])))]
     (let [current-page (:type @(subscribe [:page]))]
       (when (not= @prev-page current-page)
-        (when (= @prev-page :search)
-          (reset! search-query ""))
+        (if (= @prev-page :search)
+          (reset! search-query "")
+          (reset! search-query @(subscribe [:braid.search/query])))
         (reset! prev-page current-page)))
     [:div.search-bar
      [:input {:type "text"


species.clj edited online with Bitbucket

--- resources/species.clj
+++ resources/species.clj
@@ -3,13 +3,20 @@
                  :min-size 100
                  :production-rate 0.02
                  :influence {:detrit 1e-20
-                             :oxygen 1e-20}}
- :lichens {:size 0.3e6
+                             :oxygen 1e-20}
+                 :tolerance {:detrit {:model :limit
+                                      :ideal 40
+                                      :radius 1.5}}}
+
+:lichens {:size 3e5
            :max-size 1e6
            :min-size 10
-           :production-rate 2e-3
-           :influence {:detrit 0.4e-6
-                       :oxygen 0.2e-6}}
+           :production-rate 7e-3
+           :influence {:detrit 4e-6
+                       :oxygen 0.3e-6}
+         :tolerance {:detrit {:model :limit
+                                :ideal 110
+                                :radius 20}}}
  :soilbacteria {:size 0.3e30
                 :max-size 1e30
                 :min-size 100
@@ -85,4 +92,4 @@
                                    :radius -1}}
                 :influence {:detrit 0.4
                             :oxygen 2
-                            :soil -0.5}}}
+                            :soil -0.5}}}


When the Spec is empty, don't use it. Also removes some duplicate code, and passes job-name to the right places.

--- src/circle/backend/build/config.clj
+++ src/circle/backend/build/config.clj
@@ -64,13 +64,13 @@
   (->> spec
        ((juxt :setup :dependencies :compile :test))
        (mapcat (fn [line]
-                 (str/split line #"\r\n")))
+                 (str/split (or line "") #"\r\n")))
        (filter #(> (.length %) 0))))

 (defn get-config-from-db [url]
   (let [project (project/get-by-url url)]
     (when-let [spec (spec/get-spec-for-project project)]
-      (when-let [commands (spec-commands spec)]
+      (when-let [commands (seq (spec-commands spec))]
         (db-config commands)))))

 (defn get-config-for-url
@@ -265,16 +265,12 @@
   "Given a project url and a build name, return a build. Helper method for repl"
   [url & {:keys [job-name vcs-revision]}]
   (let [project (project/get-by-url! url)
-        repo (git/default-repo-path url)
-        vcs-revision (or vcs-revision (git/latest-local-commit repo))
-        config (get-config-for-url url :vcs_revision vcs-revision)
-        job-name (or job-name (-> config :jobs (first)))]
+        config (get-config-for-url url :vcs_revision vcs-revision)]
     (if (and config project)
-      (let [job-name (or (-> config :schedule :commit :job (keyword)) (-> config :jobs (first) (key)))]
-        (build-from-config config project
-                           :vcs_revision vcs-revision
-                           :notify ["founders@circleci.com"] ;; (-> config :jobs job-name :notify_emails (parse-notify) (get-build-email-recipients github-json))
-                           ))
+      (build-from-config config project
+                         :vcs_revision vcs-revision
+                         :notify ["founders@circleci.com"] ;; (-> config :jobs job-name :notify_emails (parse-notify) (get-build-email-recipients github-json))
+                         :job-name job-name)
       (infer-build-from-url url))))

 (defn build-from-json


Remove deleted examples from recently updated section. Fixes #75.

--- src/clj/clojuredocs/pages/intro.clj
+++ src/clj/clojuredocs/pages/intro.clj
@@ -210,7 +210,10 @@

 (defn recently-updated []
   (let [limit 6
-        examples (->> (mon/fetch :examples :sort {:created-at -1} :limit limit)
+        examples (->> (mon/fetch :examples
+                        :where {:deleted-at nil}
+                        :sort {:created-at -1}
+                        :limit limit)
                       (map #(assoc % :type :example)))
         see-alsos (->> (mon/fetch :see-alsos :sort {:created-at -1} :limit limit)
                        (map #(assoc % :type :see-also)))


Add looped playback

Add looped playback

--- src/cljs/asciinema_player/core.cljs
+++ src/cljs/asciinema_player/core.cljs
@@ -19,6 +19,7 @@
          :play-from 0
          :current-time 0
          :autoplay false
+         :loop false
          :speed 1.0}))

 (defn apply-changes [state changes]
@@ -145,7 +146,9 @@
   (let [position (new-position (:current-time state) (:duration state) 5)]
     (handle-seek state dispatch [position])))

-(defn handle-finished [state _]
+(defn handle-finished [state dispatch]
+  (when (:loop state)
+    (dispatch [:toggle-play]))
   (-> state (dissoc :stop) (assoc :play-from 0)))

 (defn speed-up [speed]


No need for goog.dom for just getElementById

--- src/cljs/asciinema_player/core.cljs
+++ src/cljs/asciinema_player/core.cljs
@@ -1,6 +1,5 @@
 (ns asciinema-player.core
-  (:require [goog.dom :as dom]
-            [reagent.core :as reagent :refer [atom]]
+  (:require [reagent.core :as reagent :refer [atom]]
             [asciinema-player.view :as view]
             [asciinema-player.util :as util]
             [cljs.core.async :refer [chan >! <! timeout close!]]
@@ -215,7 +214,7 @@
     (clj->js {:toggle (fn [] true)})))

 (defn create-player [dom-node width height frames-url duration options]
-  (let [dom-node (if (string? dom-node) (dom/getElement dom-node) dom-node)
+  (let [dom-node (if (string? dom-node) (.getElementById js/document dom-node) dom-node)
         state (make-player-state width height frames-url duration options)]
     (create-player-with-state state dom-node)))


Remove unnecessary require

Remove unnecessary require

--- src/clojure/nightcode/shortcuts.clj
+++ src/clojure/nightcode/shortcuts.clj
@@ -1,8 +1,7 @@
 (ns nightcode.shortcuts
   (:require [nightcode.utils :as utils]
             [seesaw.core :as s]
-            [seesaw.keymap :as keymap]
-            [seesaw.keystroke :as keystroke])
+            [seesaw.keymap :as keymap])
   (:import [java.awt Toolkit]
            [java.awt Color KeyboardFocusManager KeyEventDispatcher]
            [java.awt.event ActionEvent KeyEvent]


UMM validation needs to be called from validation endpoint

--- ingest-app/src/cmr/ingest/services/ingest.clj
+++ ingest-app/src/cmr/ingest/services/ingest.clj
@@ -77,7 +77,9 @@
   Return an appropriate error message indicating any validation failures."
   [context concept]
   (v/validate-concept-request concept)
-  (v/validate-concept-xml concept))
+  (v/validate-concept-xml concept)
+  (let [umm-record (umm/parse-concept concept)]
+    (v/validate-umm-record (:format concept) umm-record)))

 (deftracefn save-concept
   "Store a concept in mdb and indexer and return concept-id and revision-id."


Om-nextify sidebar

Om-nextify sidebar

--- src/discuss/components/sidebar.cljs
+++ src/discuss/components/sidebar.cljs
@@ -1,10 +1,10 @@
 (ns discuss.components.sidebar
   "Controlling the sidebar."
-  (:require [om.core :as om]
-            [om.dom :as dom]
-            [goog.dom :as gdom]
+  (:require [om.next :as om :refer-macros [defui]]
+            [sablono.core :refer-macros [html]]
             [discuss.utils.common :as lib]
-            [discuss.utils.views :as vlib]))
+            [discuss.utils.views :as vlib]
+            [goog.dom :as gdom]))

 (def id (lib/prefix-name "sidebar"))

@@ -35,9 +35,12 @@

 ;;;; Sidebar
-(defn view [data]
-  (reify om/IRender
-    (render [_]
-      (dom/div nil
-               (vlib/fa-icon "fa-bars" hide)
-               (om/build (resolve 'discuss.views/main-view) data)))))
+(defui Sidebar
+  Object
+  (render [this]
+          (html
+           [:div
+            [:div.discuss-sidebar
+             (vlib/fa-icon "fa-bars" hide)
+             ((resolve 'discuss.views/main-view) (om/props this))]])))
+(def sidebar (om/factory Sidebar {:keyfn identity}))


Revert "refactor using a threading macro (->>)"

This reverts commit fc4e9162ea1977430a7a7f7ae9690bce40fc80d1.

--- src/babel/italiano/morphology.cljc
+++ src/babel/italiano/morphology.cljc
@@ -1405,346 +1405,346 @@
           (let [lexemes (get lexicon k)
                 lexeme-kv [k lexemes]]
             (if lexemes
-              (->> lexemes
-                   (mapcat (fn [path-and-merge-fn]
-                             (let [path (:path path-and-merge-fn)
-                                   surface-form-fn (if (:surface-form path-and-merge-fn)
-                                                     (:surface-form path-and-merge-fn)
-                                                     (fn [lexeme]
-                                                       (get-in lexeme path :none)))
-                                   merge-fn (:merge-fn path-and-merge-fn)]
-                               ;; a lexeme-kv is a pair of a key and value. The key is a string (the word's surface form)
-                               ;; and the value is a list of lexemes for that string.
-                               (log/trace (str "lexeme key:" k))
-                               (log/trace (str (first lexeme-kv) " generating exception for path: " path))
-                               (mapcat (fn [lexeme]
-                                         ;; this is where a unify/dissoc that supported
-                                         ;; non-maps like :top and :fail, would be useful:
-                                         ;; would not need the (if (not (fail? lexeme)..)) check
-                                         ;; to avoid a difficult-to-understand "java.lang.ClassCastException:
-                                         ;; clojure.lang.Keyword cannot be cast to clojure.lang.IPersistentMap" error.
-                                         (let [debug (log/debug (str "lexeme: " lexeme))
-                                               lexeme (cond (= lexeme :fail)
-                                                            :fail
-                                                            (= lexeme :top)
-                                                            :top
-                                                            true
-                                                            lexeme)]
-                                           ;; not copying this time
-                                           ;;                                                                    (dissoc (copy lexeme) :serialized))]
-                                           (if (not (= :none (get-in lexeme path :none)))
-                                             (do (log/debug (str (first lexeme-kv) " generating lexeme exceptional surface form: " (surface-form-fn lexeme)))
-                                                 (list {(surface-form-fn lexeme)
-                                                        [(reduce
-                                                          (fn [a b]
-                                                            (cond
-                                                              (= a :fail)
-                                                              (do
-                                                                (log/warn (str ":fail in exception rule:"
-                                                                               (:label path-and-merge-fn)
-                                                                               "; lexeme's italiano:"
-                                                                               (strip-refs (get-in lexeme [:italiano]))))
-                                                                :fail)
-                                                              (= b :fail)
-                                                              (do
-                                                                (log/warn (str ":fail in exception rule:"
-                                                                               (:label path-and-merge-fn)
-                                                                               "; lexeme:"
-                                                                               (or (strip-refs (get-in lexeme [:italiano :italiano]))
-                                                                                (strip-refs (get-in lexeme [:italiano])))))
-                                                                :fail)
-                                                              true
-                                                              (unify a b)))
-                                                          [(dissoc-paths lexeme [[:italiano :italiano]])
-                                                           (merge-fn lexeme)
-                                                           {:italiano {:infinitive k
-                                                                       :exception true}}])]})))))
-                                       lexemes)))
-                           [
-                            ;; 1. past-tense exceptions
-                            {:path [:italiano :passato]
-                             :label "past-tense exception"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :past
-                                           :italiano (get-in val [:italiano :passato] :nothing)}})}
-
-                            ;; 1.5 imperfect
-                            {:path [:italiano :imperfect :1sing]
-                             :label "imperfect 1sing"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :imperfect
-                                           :italiano (get-in val [:italiano :imperfect :1sing] :nothing)
-                                           :agr {:number :sing
-                                                 :person :1st}}})}
-                            {:path [:italiano :imperfect :2sing]
-                             :label "imperfect 2sing"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :imperfect
-                                           :italiano (get-in val [:italiano :imperfect :2sing] :nothing)
-                                           :agr {:number :sing
-                                                 :person :2nd}}})}
-
-                            {:path [:italiano :imperfect :3sing]
-                             :label "imperfect 3sing"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :imperfect
-                                           :italiano (get-in val [:italiano :imperfect :3sing] :nothing)
-                                           :agr {:number :sing
-                                                 :person :3rd}}})}
-
-                            {:path [:italiano :imperfect :1plur]
-                             :label "imperfect 1plur"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :imperfect
-                                           :italiano (get-in val [:italiano :imperfect :1plur] :nothing)
-                                           :agr {:number :plur
-                                                 :person :1st}}})}
-
-                            {:path [:italiano :imperfect :2plur]
-                             :label "imperfect 2plur"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :imperfect
-                                           :italiano (get-in val [:italiano :imperfect :2plur] :nothing)
-                                           :agr {:number :plur
-                                                 :person :2nd}}})}
-
-                            {:path [:italiano :imperfect :3plur]
-                             :label "imperfect 3plur"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :imperfect
-                                           :italiano (get-in val [:italiano :imperfect :3plur] :nothing)
-                                           :agr {:number :plur
-                                                 :person :3rd}}})}
-
-                            ;; 2. present-tense exceptions
-                            {:path [:italiano :present :1sing]
-                             :label "present 1sing"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :present
-                                           :italiano (get-in val [:italiano :present :1sing] :nothing)
-                                           :agr {:number :sing
-                                                 :person :1st}}})}
-                            {:path [:italiano :present :2sing]
-                             :label "present 2sing"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :present
-                                           :italiano (get-in val [:italiano :present :2sing] :nothing)
-                                           :agr {:number :sing
-                                                 :person :2nd}}})}
-
-                            {:path [:italiano :present :3sing]
-                             :label "present 3sing"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :present
-                                           :italiano (get-in val [:italiano :present :3sing] :nothing)
-                                           :agr {:number :sing
-                                                 :person :3rd}}})}
-
-                            {:path [:italiano :present :1plur]
-                             :label "present 1plur"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :present
-                                           :italiano (get-in val [:italiano :present :1plur] :nothing)
-                                           :agr {:number :plur
-                                                 :person :1st}}})}
-
-                            {:path [:italiano :present :2plur]
-                             :label "present 2plur"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :present
-                                           :italiano (get-in val [:italiano :present :2plur] :nothing)
-                                           :agr {:number :plur
-                                                 :person :2nd}}})}
-
-                            {:path [:italiano :present :3plur]
-                             :label "present 3plur"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :present
-                                           :italiano (get-in val [:italiano :present :3plur] :nothing)
-                                           :agr {:number :plur
-                                                 :person :3rd}}})}
-
-                            ;; 2.1. present tense boot-stem
-                            (let [surface-form (fn [val] (str (get-in val [:italiano :boot-stem1]) "o"))]
-                              {:path [:italiano :boot-stem1]
-                               :label "present boot-stem1: o"
-                               :surface-form surface-form
-                               :merge-fn
-                               (fn [val]
-                                 {:italiano {:infl :present
-                                             :italiano (surface-form val)
-                                             :agr {:number :sing
-                                                   :person :1st}}})})
-
-                            (let [surface-form (fn [val] (str (get-in val [:italiano :boot-stem1]) "i"))]
-                              {:path [:italiano :boot-stem1]
-                               :label "present boot-stem1: i"
-                               :surface-form surface-form
-                               :merge-fn
-                               (fn [val]
-                                 {:italiano {:infl :present
-                                             :italiano (surface-form val)
-                                             :agr {:number :sing
-                                                   :person :2nd}}})})
-
-                            (let [surface-form (fn [val] (str (get-in val [:italiano :boot-stem1]) "e"))]
-                              {:path [:italiano :boot-stem1]
-                               :label "present boot-stem1: e"
-                               :surface-form surface-form
-                               :merge-fn
-                               (fn [val]
-                                 {:italiano {:infl :present
-                                             :italiano (surface-form val)
-                                             :agr {:number :sing
-                                                   :person :3rd}}})})
-
-                            (let [surface-form (fn [val] (str (get-in val [:italiano :boot-stem1]) "ono"))]
-                              {:path [:italiano :boot-stem1]
-                               :label "present boot-stem1: ono"
-                               :surface-form surface-form
-                               :merge-fn
-                               (fn [val]
-                                 {:italiano {:infl :present
-                                             :italiano (surface-form val)
-                                             :agr {:number :plur
-                                                   :person :3rd}}})})
-
-                            ;; 3. future-tense exceptions
-                            {:path [:italiano :future :1sing]
-                             :label "future 1sing"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :future
-                                           :italiano (get-in val [:italiano :future :1sing] :nothing)
-                                           :agr {:number :sing
-                                                 :person :1st}}})}
-                            {:path [:italiano :future :2sing]
-                             :label "future 2sing"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :future
-                                           :italiano (get-in val [:italiano :future :2sing] :nothing)
-                                           :agr {:number :sing
-                                                 :person :2nd}}})}
-                            {:path [:italiano :future :3sing]
-                             :label "future 3sing"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :future
-                                           :italiano (get-in val [:italiano :future :3sing] :nothing)
-                                           :agr {:number :sing
-                                                 :person :3rd}}})}
-                            {:path [:italiano :future :1plur]
-                             :label "future 1plur"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :future
-                                           :italiano (get-in val [:italiano :future :1plur] :nothing)
-                                           :agr {:number :plur
-                                                 :person :1st}}})}
-                            {:path [:italiano :future :2plur]
-                             :label "future 2plur"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :future
-                                           :italiano (get-in val [:italiano :future :2plur] :nothing)
-                                           :agr {:number :plur
-                                                 :person :2nd}}})}
-                            {:path [:italiano :future :3plur]
-                             :label "future 3plur"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :future
-                                           :italiano (get-in val [:italiano :future :3plur] :nothing)
-                                           :agr {:number :plur
-                                                 :person :3rd}}})}
-
-                            ;; 4. conditional-tense exceptions
-                            {:path [:italiano :conditional :1sing]
-                             :label "conditional 1sing"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :conditional
-                                           :italiano (get-in val [:italiano :conditional :1sing] :nothing)
-                                           :agr {:number :sing
-                                                 :person :1st}}})}
-                            {:path [:italiano :conditional :2sing]
-                             :label "conditional 2sing"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :conditional
-                                           :italiano (get-in val [:italiano :conditional :2sing] :nothing)
-                                           :agr {:number :sing
-                                                 :person :2nd}}})}
-                            {:path [:italiano :conditional :3sing]
-                             :label "conditional 3sing"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :conditional
-                                           :italiano (get-in val [:italiano :conditional :3sing] :nothing)
-                                           :agr {:number :sing
-                                                 :person :3rd}}})}
-                            {:path [:italiano :conditional :1plur]
-                             :label "conditional 1plur"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :conditional
-                                           :italiano (get-in val [:italiano :conditional :1plur] :nothing)
-                                           :agr {:number :plur
-                                                 :person :1st}}})}
-                            {:path [:italiano :conditional :2plur]
-                             :label "conditional 2plur"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :conditional
-                                           :italiano (get-in val [:italiano :conditional :2plur] :nothing)
-                                           :agr {:number :plur
-                                                 :person :2nd}}})}
-                            {:path [:italiano :conditional :3plur]
-                             :label "conditional 3plur"
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:infl :conditional
-                                           :italiano (get-in val [:italiano :conditional :3plur] :nothing)
-                                           :agr {:number :plur
-                                                 :person :3rd}}})}
-                            ;; adjectives
-                            {:path [:italiano :masc :plur]
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:agr {:gender :masc
-                                                 :number :plur}}})}
-
-                            {:path [:italiano :fem :plur]
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:agr {:gender :fem
-                                                 :number :plur}}})}
-                            {:path [:italiano :fem :sing]
-                             :merge-fn
-                             (fn [val]
-                               {:italiano {:agr {:gender :fem
-                                                 :number :sing}}})}
-                            ;; nouns
-                            {:path [:italiano :plur]
-                             :merge-fn
-                             (fn [val]
-                               {:synsem {:cat :noun}
-                                :italiano {:agr {:number :plur}}})}
-                            ])))))
+              (let [result (mapcat (fn [path-and-merge-fn]
+                                     (let [path (:path path-and-merge-fn)
+                                           surface-form-fn (if (:surface-form path-and-merge-fn)
+                                                             (:surface-form path-and-merge-fn)
+                                                             (fn [lexeme]
+                                                               (get-in lexeme path :none)))
+                                           merge-fn (:merge-fn path-and-merge-fn)]
+                                       ;; a lexeme-kv is a pair of a key and value. The key is a string (the word's surface form)
+                                       ;; and the value is a list of lexemes for that string.
+                                       (log/trace (str "lexeme key:" k))
+                                       (log/trace (str (first lexeme-kv) " generating exception for path: " path))
+                                       (mapcat (fn [lexeme]
+                                                 ;; this is where a unify/dissoc that supported
+                                                 ;; non-maps like :top and :fail, would be useful:
+                                                 ;; would not need the (if (not (fail? lexeme)..)) check
+                                                 ;; to avoid a difficult-to-understand "java.lang.ClassCastException:
+                                                 ;; clojure.lang.Keyword cannot be cast to clojure.lang.IPersistentMap" error.
+                                                 (let [debug (log/debug (str "lexeme: " lexeme))
+                                                       lexeme (cond (= lexeme :fail)
+                                                                    :fail
+                                                                    (= lexeme :top)
+                                                                    :top
+                                                                    true
+                                                                    lexeme)]
+                                                                    ;; not copying this time
+;;                                                                    (dissoc (copy lexeme) :serialized))]
+                                                   (if (not (= :none (get-in lexeme path :none)))
+                                                     (do (log/debug (str (first lexeme-kv) " generating lexeme exceptional surface form: " (surface-form-fn lexeme)))
+                                                         (list {(surface-form-fn lexeme)
+                                                                [(reduce
+                                                                  (fn [a b]
+                                                                    (cond
+                                                                      (= a :fail)
+                                                                      (do
+                                                                        (log/warn (str ":fail in exception rule:"
+                                                                                (:label path-and-merge-fn)
+                                                                                "; lexeme's italiano:"
+                                                                                (strip-refs (get-in lexeme [:italiano]))))
+                                                                        :fail)
+                                                                      (= b :fail)
+                                                                      (do
+                                                                        (log/warn (str ":fail in exception rule:"
+                                                                                (:label path-and-merge-fn)
+                                                                                "; lexeme:"
+                                                                                (or (strip-refs (get-in lexeme [:italiano :italiano]))
+                                                                                (strip-refs (get-in lexeme [:italiano])))))
+                                                                        :fail)
+                                                                      true
+                                                                      (unify a b)))
+                                                                  [(dissoc-paths lexeme [[:italiano :italiano]])
+                                                                   (merge-fn lexeme)
+                                                                   {:italiano {:infinitive k
+                                                                               :exception true}}])]})))))
+                                               lexemes)))
+                                   [
+                                    ;; 1. past-tense exceptions
+                                    {:path [:italiano :passato]
+                                     :label "past-tense exception"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :past
+                                                   :italiano (get-in val [:italiano :passato] :nothing)}})}
+
+                                    ;; 1.5 imperfect
+                                    {:path [:italiano :imperfect :1sing]
+                                     :label "imperfect 1sing"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :imperfect
+                                                   :italiano (get-in val [:italiano :imperfect :1sing] :nothing)
+                                                   :agr {:number :sing
+                                                         :person :1st}}})}
+                                    {:path [:italiano :imperfect :2sing]
+                                     :label "imperfect 2sing"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :imperfect
+                                                   :italiano (get-in val [:italiano :imperfect :2sing] :nothing)
+                                                   :agr {:number :sing
+                                                         :person :2nd}}})}
+
+                                    {:path [:italiano :imperfect :3sing]
+                                     :label "imperfect 3sing"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :imperfect
+                                                   :italiano (get-in val [:italiano :imperfect :3sing] :nothing)
+                                                   :agr {:number :sing
+                                                         :person :3rd}}})}
+
+                                    {:path [:italiano :imperfect :1plur]
+                                     :label "imperfect 1plur"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :imperfect
+                                                   :italiano (get-in val [:italiano :imperfect :1plur] :nothing)
+                                                   :agr {:number :plur
+                                                         :person :1st}}})}
+
+                                    {:path [:italiano :imperfect :2plur]
+                                     :label "imperfect 2plur"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :imperfect
+                                                   :italiano (get-in val [:italiano :imperfect :2plur] :nothing)
+                                                   :agr {:number :plur
+                                                         :person :2nd}}})}
+
+                                    {:path [:italiano :imperfect :3plur]
+                                     :label "imperfect 3plur"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :imperfect
+                                                   :italiano (get-in val [:italiano :imperfect :3plur] :nothing)
+                                                   :agr {:number :plur
+                                                         :person :3rd}}})}
+
+                                    ;; 2. present-tense exceptions
+                                    {:path [:italiano :present :1sing]
+                                     :label "present 1sing"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :present
+                                                   :italiano (get-in val [:italiano :present :1sing] :nothing)
+                                                   :agr {:number :sing
+                                                         :person :1st}}})}
+                                    {:path [:italiano :present :2sing]
+                                     :label "present 2sing"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :present
+                                                   :italiano (get-in val [:italiano :present :2sing] :nothing)
+                                                   :agr {:number :sing
+                                                         :person :2nd}}})}
+
+                                    {:path [:italiano :present :3sing]
+                                     :label "present 3sing"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :present
+                                                   :italiano (get-in val [:italiano :present :3sing] :nothing)
+                                                   :agr {:number :sing
+                                                         :person :3rd}}})}
+
+                                    {:path [:italiano :present :1plur]
+                                     :label "present 1plur"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :present
+                                                   :italiano (get-in val [:italiano :present :1plur] :nothing)
+                                                   :agr {:number :plur
+                                                         :person :1st}}})}
+
+                                    {:path [:italiano :present :2plur]
+                                     :label "present 2plur"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :present
+                                                   :italiano (get-in val [:italiano :present :2plur] :nothing)
+                                                   :agr {:number :plur
+                                                         :person :2nd}}})}
+
+                                    {:path [:italiano :present :3plur]
+                                     :label "present 3plur"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :present
+                                                   :italiano (get-in val [:italiano :present :3plur] :nothing)
+                                                   :agr {:number :plur
+                                                         :person :3rd}}})}
+
+                                    ;; 2.1. present tense boot-stem
+                                    (let [surface-form (fn [val] (str (get-in val [:italiano :boot-stem1]) "o"))]
+                                      {:path [:italiano :boot-stem1]
+                                       :label "present boot-stem1: o"
+                                       :surface-form surface-form
+                                       :merge-fn
+                                       (fn [val]
+                                         {:italiano {:infl :present
+                                                     :italiano (surface-form val)
+                                                     :agr {:number :sing
+                                                           :person :1st}}})})
+
+                                    (let [surface-form (fn [val] (str (get-in val [:italiano :boot-stem1]) "i"))]
+                                      {:path [:italiano :boot-stem1]
+                                       :label "present boot-stem1: i"
+                                       :surface-form surface-form
+                                       :merge-fn
+                                       (fn [val]
+                                         {:italiano {:infl :present
+                                                     :italiano (surface-form val)
+                                                     :agr {:number :sing
+                                                           :person :2nd}}})})
+
+                                    (let [surface-form (fn [val] (str (get-in val [:italiano :boot-stem1]) "e"))]
+                                      {:path [:italiano :boot-stem1]
+                                       :label "present boot-stem1: e"
+                                       :surface-form surface-form
+                                       :merge-fn
+                                       (fn [val]
+                                         {:italiano {:infl :present
+                                                     :italiano (surface-form val)
+                                                     :agr {:number :sing
+                                                           :person :3rd}}})})
+
+                                    (let [surface-form (fn [val] (str (get-in val [:italiano :boot-stem1]) "ono"))]
+                                      {:path [:italiano :boot-stem1]
+                                       :label "present boot-stem1: ono"
+                                       :surface-form surface-form
+                                       :merge-fn
+                                       (fn [val]
+                                         {:italiano {:infl :present
+                                                     :italiano (surface-form val)
+                                                     :agr {:number :plur
+                                                           :person :3rd}}})})
+
+                                    ;; 3. future-tense exceptions
+                                    {:path [:italiano :future :1sing]
+                                     :label "future 1sing"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :future
+                                                   :italiano (get-in val [:italiano :future :1sing] :nothing)
+                                                   :agr {:number :sing
+                                                         :person :1st}}})}
+                                    {:path [:italiano :future :2sing]
+                                     :label "future 2sing"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :future
+                                                   :italiano (get-in val [:italiano :future :2sing] :nothing)
+                                                   :agr {:number :sing
+                                                         :person :2nd}}})}
+                                    {:path [:italiano :future :3sing]
+                                     :label "future 3sing"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :future
+                                                   :italiano (get-in val [:italiano :future :3sing] :nothing)
+                                                   :agr {:number :sing
+                                                         :person :3rd}}})}
+                                    {:path [:italiano :future :1plur]
+                                     :label "future 1plur"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :future
+                                                   :italiano (get-in val [:italiano :future :1plur] :nothing)
+                                                   :agr {:number :plur
+                                                         :person :1st}}})}
+                                    {:path [:italiano :future :2plur]
+                                     :label "future 2plur"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :future
+                                                   :italiano (get-in val [:italiano :future :2plur] :nothing)
+                                                   :agr {:number :plur
+                                                         :person :2nd}}})}
+                                    {:path [:italiano :future :3plur]
+                                     :label "future 3plur"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :future
+                                                   :italiano (get-in val [:italiano :future :3plur] :nothing)
+                                                   :agr {:number :plur
+                                                         :person :3rd}}})}
+
+                                    ;; 4. conditional-tense exceptions
+                                    {:path [:italiano :conditional :1sing]
+                                     :label "conditional 1sing"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :conditional
+                                                   :italiano (get-in val [:italiano :conditional :1sing] :nothing)
+                                                   :agr {:number :sing
+                                                         :person :1st}}})}
+                                    {:path [:italiano :conditional :2sing]
+                                     :label "conditional 2sing"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :conditional
+                                                   :italiano (get-in val [:italiano :conditional :2sing] :nothing)
+                                                   :agr {:number :sing
+                                                         :person :2nd}}})}
+                                    {:path [:italiano :conditional :3sing]
+                                     :label "conditional 3sing"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :conditional
+                                                   :italiano (get-in val [:italiano :conditional :3sing] :nothing)
+                                                   :agr {:number :sing
+                                                         :person :3rd}}})}
+                                    {:path [:italiano :conditional :1plur]
+                                     :label "conditional 1plur"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :conditional
+                                                   :italiano (get-in val [:italiano :conditional :1plur] :nothing)
+                                                   :agr {:number :plur
+                                                         :person :1st}}})}
+                                    {:path [:italiano :conditional :2plur]
+                                     :label "conditional 2plur"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :conditional
+                                                   :italiano (get-in val [:italiano :conditional :2plur] :nothing)
+                                                   :agr {:number :plur
+                                                         :person :2nd}}})}
+                                    {:path [:italiano :conditional :3plur]
+                                     :label "conditional 3plur"
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:infl :conditional
+                                                   :italiano (get-in val [:italiano :conditional :3plur] :nothing)
+                                                   :agr {:number :plur
+                                                         :person :3rd}}})}
+                                    ;; adjectives
+                                    {:path [:italiano :masc :plur]
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:agr {:gender :masc
+                                                         :number :plur}}})}
+
+                                    {:path [:italiano :fem :plur]
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:agr {:gender :fem
+                                                         :number :plur}}})}
+                                    {:path [:italiano :fem :sing]
+                                     :merge-fn
+                                     (fn [val]
+                                       {:italiano {:agr {:gender :fem
+                                                         :number :sing}}})}
+                                    ;; nouns
+                                    {:path [:italiano :plur]
+                                     :merge-fn
+                                     (fn [val]
+                                       {:synsem {:cat :noun}
+                                        :italiano {:agr {:number :plur}}})}
+                                    ])]
+                result))))
         (sort (keys lexicon)))))

 (defn phonize2 [lexicon]