this program opens a file read it into a list
then asks the user to enter the word from the list one at a time
but I get an error right after it speaks
(ns EKS.Core)
(use '[speech-synthesis.say :as say])
(use '[clojure.java.shell :only [sh]])
(use 'seesaw.core)
(use 'seesaw.dev)
(use 'seesaw.chooser)
(use 'clojure.java.io)
(import 'java.io.File)
(native!)
(defn festival [x](sh "sh" "-c" (str "echo " x " | festival --tts")))
(defn espeak [x] (sh "espeak" x))
(defn mac-say[x] (sh "say" x))
(defn check-if-installed[x] (:exit(sh "sh" "-c" (str "command -v " x " >/dev/null 2>&1 || { echo >&2 \"\"; exit 1; }"))))
(defn env
"Returns the system property for user.<key>"
[key]
(System/getProperty (str "user." key)))
(defn get-lines [fname]
(with-open [r (reader fname)]
(doall (line-seq r))))
(defn engine-check[]
(def engines (conj["Google" ]
(if (= (check-if-installed "festival") 0) "Festival" )
(if (= (check-if-installed "espeak") 0) "ESpeak" )
(if (= (check-if-installed "say") 0) "Say" )))(remove nil? engines))
(engine-check)
(def ListDir (str (env "home") ))
(def speak say)
(defn setup-list[ file](
(def ListEntry (remove #{""} (get-lines (.getAbsolutePath file))))
(speak (str "Enter the word " (first ListEntry)))
(.getAbsolutePath file)
(def current 0)))
(def Open-Action (action :handler (fn [e] (choose-file :type :open :selection-mode :files-only :dir ListDir :success-fn (fn [fc file](setup-list file))))
:name "Open"
:key "menu O"
:tip "Open list"))
(def entry-text(text :id :entry :text "" ))
(defn check-word[] ((if (= (text entry-text) (nth ListEntry current))(speak "correct")(speak "incorrect"))(def current (+ current 1))(speak (str "Enter the word " (nth ListEntry current)))))
(def Main-Panel(grid-panel :vgap 7 :hgap 20 :border "Main" :items[ (top-bottom-split entry-text
(left-right-split (grid-panel :vgap 7 :items[(label :text "Correct: 0") (label :text "Incorrect: 0")]) (grid-panel :vgap 7 :items[(button :text "Next"
:mnemonic \N
:listen [:action (fn [e] (check-word))])
(button :text "Repeat!"
:mnemonic \\
:listen [:action (fn[e] (speak(nth ListEntry current)))])
]) :divider-location 1/3 )
:divider-location 1/3 )]))
(def Main-Window(frame :title "??????", :on-close :exit, :size[425 :by 172]:menubar(menubar :items[(menu :text "File" :items [Open-Action ])]) :content Main-Panel ))
(show! Main-Window)
this is the error message I get when opening a file
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn
at clojure.lang.Var.fn(Var.java:378)
at clojure.lang.Var.invoke(Var.java:409)
at EKS.Core$setup_list.invoke(NO_SOURCE_FILE:38)
at EKS.Core$fn__5794$fn__5795.invoke(NO_SOURCE_FILE:42)
at seesaw.chooser$choose_file.doInvoke(chooser.clj:173)
at clojure.lang.RestFn.invoke(RestFn.java:619)
at EKS.Core$fn__5794.invoke(NO_SOURCE_FILE:42)
at seesaw.action$action$fn__1218.invoke(action.clj:90)
at seesaw.action.proxy$javax.swing.AbstractAction$0.actionPerformed(Unknown Source)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
at java.awt.Component.processMouseEvent(Component.java:6505)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6270)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4861)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:713)
at java.awt.EventQueue.access$000(EventQueue.java:104)
at java.awt.EventQueue$3.run(EventQueue.java:672)
at java.awt.EventQueue$3.run(EventQueue.java:670)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:686)
at java.awt.EventQueue$4.run(EventQueue.java:684)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:683)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)
this is the test file I am using
this
here
word
What I believe is causing the traceback is:
Notice the paren after
[ file]. You’re calling def (which is probably not what you mean to do), but the result of that def is a lazy sequence (because ofremove) and it being called as a function because of that paren. Unfortunately, it’s not clear what you’re trying to do withsetup-list, otherwise I’d write something more idiomatic for you.There a few other things you should consider. First, don’t use
(def ...)inside a function that’s really bad form. In this case, I think what you’re really after is(let ...):It would also help you to see what’s going on if you could keep a little more structure to the code. I think the formatting is letting things like that paren hide, where it may have been more obvious if you had a better style:
Here, it’s little more clear that the def will be used as a function call, which is probably not what you want.
BTW, Clojure has some Library Coding Standards. They’ve got some good things in there. And Ring is an excellent example to follow for a code base, as is Seesaw.