This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-04-05
Channels
- # architecture (2)
- # aws (1)
- # bangalore-clj (4)
- # beginners (97)
- # boot (35)
- # cider (8)
- # cljsjs (3)
- # cljsrn (35)
- # clojure (190)
- # clojure-dusseldorf (4)
- # clojure-italy (7)
- # clojure-poland (1)
- # clojure-russia (17)
- # clojure-spec (74)
- # clojure-uk (30)
- # clojureremote (2)
- # clojurescript (298)
- # code-reviews (18)
- # component (18)
- # cursive (18)
- # datascript (3)
- # datavis (2)
- # datomic (24)
- # dirac (17)
- # emacs (3)
- # garden (7)
- # hoplon (51)
- # jobs (2)
- # jobs-rus (2)
- # leiningen (4)
- # luminus (11)
- # mount (24)
- # off-topic (1)
- # om (32)
- # onyx (25)
- # pedestal (1)
- # powderkeg (9)
- # protorepl (6)
- # re-frame (11)
- # reagent (15)
- # spacemacs (6)
- # sql (35)
- # uncomplicate (1)
- # unrepl (74)
- # untangled (130)
- # yada (6)
@rmuslimov Perhaps you can provide more details about your REPL and Java class problem here?
(defproject clj-soap-srv "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url ""
:license {:name "Eclipse Public License"
:url ""}
:dependencies [[org.clojure/clojure "1.9.0-alpha14"]
[com.stuartsierra/component "0.3.2"]
[ "2.0"]
[reloaded.repl "0.2.3"]]
:main ^:skip-aot clj-soap-srv.core
:target-path "target/%s"
:source-paths ["src/clj"]
:java-source-paths ["src/java"]
:profiles {:dev {:source-paths ["dev"]}
:user {:plugins [[refactor-nrepl "2.3.0-SNAPSHOT"]
[cider/cider-nrepl "0.15.0-SNAPSHOT"]]}
:uberjar {:aot :all}})
for example I have class in src/java
package org.opentravel.ota._2003._05;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"successAndWarningsAndEchoData",
"errors"
})
@XmlRootElement(name = "OTA_PingRS")
public class OTAPingRS {
And here is exception I’ve got
Caused by: java.lang.ClassNotFoundException: org.opentravel.ota._2003._05.OTAPingRQ, compiling:(clj_soap_srv/core.clj:1:1)
You said it worked the first time you fired up the REPL and worked with some code, but not the second time you fired up the REPL?
I’m thinking you’d need to do lein javac
to get it to compile the Java code and then lein repl
would find those compiled classes. But if you then did lein clean
it would delete the classes — so if you did lein repl
without first doing lein javac
, you wouldn’t have those compiled classes available...
[rmuslimov@haron clj-soap-srv]$ lein javac
(WARNING: user-level profile defined in project files.)
Exception in thread "main" java.lang.ExceptionInInitializerError
at clojure.main.<clinit>(main.java:20)
Caused by: java.lang.ClassNotFoundException: org.opentravel.ota._2003._05.OTAPingRQ, compiling:(clj_soap_srv/core.clj:1:1)
....
(I think you would need :prep-tasks [”javac”]
for that to happen but I’m not certain — it’s been a long time since I last used Leiningen — I switched to Boot about 18 months ago 🙂 )
I’m puzzled as to why lein javac
even tries to load the Clojure code...
Could be — ~/.lein/profiles.clj
is often the source of problems when several plugins have been added to it and then you go to work on a new project...
thank you @seancorfield
I think I found almost same case here: https://www.reddit.com/r/Clojure/comments/5f2ctk/cant_compile_java_sources_with_lein_javac/
I just checked and with a fresh project, I added a simple Java class and in the simple Clojure namespace imported it, when I run lein repl
, it compiles the Java to .class files as expected and they’re available directly.
Ah, there you go — that’s probably why Leiningen gives you that warning: (WARNING: user-level profile defined in project files.)
I would think you’d want those plugins loaded in the dev
profile, not the user
profile?
I think “best practice” is to add that sort of stuff to the dev
profile…?
(ns user
(:require [com.stuartsierra.component :as component]
[clj-soap-srv.core :refer [enabled-endpoints]]
[clj-soap-srv.utils :refer [new-jaxws-server]]
[clojure.tools.namespace.repl :refer [refresh]]
reloaded.repl))
(defn dev-system []
(component/system-map
:jax-ws (new-jaxws-server enabled-endpoints)))
(defn reload-system!
"Useful when in`lein repl`."
[]
(reloaded.repl/suspend)
(refresh)
(reloaded.repl/resume))
(reloaded.repl/set-init! #'dev-system)
thank you @seancorfield !
(do you need/want reloaded.repl
as a mainline dependency? shouldn’t that also be in the dev
profile?)
Glad you have it figured out! Leiningen profiles can be a pain when you’re first getting a dev workflow figured out (in my opinion).
you can always tell Leiningen to use a particular profile for any given task lein with-profile xyz sometask
and you can run multiple tasks with “do”: lein do task1, task2
(I think Boot makes all this stuff easier, but Leiningen is the older and more popular build tool)
hi, can anyone point me to a good tutorial / guide on doing file io in an ring/compojure handler (async) I have code like this:
(defn handle-text-2-speech [req]
(let [{:keys [content-type audio-stream]}
(polly/synthesize-speech
:text "An API for speech synthesis via AWS Polly"
:output-format "mp3"
:voice-id "Ivy")
input-stream (.getWrappedInputStream audio-stream)
filename "resources/public/tmp/speech.mp3"
_ (io/copy input-stream (io/file filename))]
(io/file filename)))
the file gets copied to the location on disk but obviously when i return
(io/file filename)
it doesnt have the contentsi need to block / await for the file to be copied but having a little trouble wrapping my head around it
if that something i would do in a thread ? with like (future …)
?
@dviramontes 1) the io/copy doesn't need to be in the let block, defn has an implicit do
2) io/copy doesn't return until the file is on disk
3) just calling io/file doesn't give you contents, it just gives you a handle that would find the contents if you read from it
@noisesmith thanks, and how would you read from it ?
slurp
, with-open
?
slurp is for text
so I think you need with-open, and a byte-array or whatever it is that is going to hold the bytes that come from that file
or if you want to send the bytes to the client, you can create an FileInputStream from the file and return that to ring
(now that I think about it, that's probably what you want)
Ok cool, thanks! I'll try it!
@noisesmith got it to work using (io/input-stream audio-stream)
You beat me to it 😃
(defn title-case [xs]
(as-> xs xs
(s/split xs #" ")
(map s/capitalize xs)
(s/join " " xs)))
is it bad practice to reuse xs as the variable name in this threading macro?in the loop/recur case I'd be tempted to use a multi-arity function and just recur to the function itself
(defn doit
([xs] (doit xs 0))
([xs acc] ....))
@zcassini I have definitely seen several people binding the name in a loop/as-> to the same name and I don't think there's much sense in renaming just for renaming's sake. I don't think it's bad practice. However, like the other answers I usually try to find other solutions where I don't have to use loop/recur or as->
Also, I would write that example as either
(defn title-case [s]
(-> s
(s/split #” ')
(->> (map s/capitalize)
(s/join “ “))))
or, more likely, as: (defn title-case [s]
(->> (s/split s #” “)
(map s/capitalize)
(s/join “ “)))
I would not use as->
here (I would only use as->
inside an already-threaded expression).@seancorfield I like how you avoided having to choose between ->
and ->>
by starting with (->> (s/split s #" "
You can mix and match ->
and ->>
if you can start with ->
(but not with ->>
). I try to avoid as->
unless I really need something in the middle of a threaded expression that has an argument not in the first/last position.
so you think
(defn title-case [xs]
(-> xs
(s/split #" ")
(->> (map s/capitalize))
(->> (s/join " " ))))
you only need one ->> block, the map and join can both be in it
Yeah, as I said, “more likely” just the ->>
form.
Subjective. I prefer it the shorter way with an actual expression in the first slot of ->>
.
I find this
(defn title-case [s]
(->> (s/split s #" ")
(map s/capitalize)
(s/join " “)))
much easier to read than (defn title-case [xs]
(-> xs
(s/split #" ")
(->> (map s/capitalize))
(->> (s/join " " ))))
Having multiple ->>
in there looks really confusing IMO.
When the syntax is new and unfamiliar, it can be hard to decide what “looks best” and I know my preferred style has changed a lot over the last six years.
@seancorfield Follow up about the use of ->>
inside ->
. Is the reason you can nest expressions of ->>
inside ->
some special macro magic?
I didn't expect this to work:
(-> "hello there you person"
(s/split #" ")
(->> (map s/capitalize)
(s/join " ")))
, thinking the map s/cap ...
line should return a function that crashes the next line.Use macroexpand
to see how ->
and ->>
behave… 🙂
They both just rewrite expressions into the nested forms.
So (-> a (b x) (c y))
produces (c (b a x) y)
and (->> a (b x) (c y))
produces (c y (b x a))
Thus (-> a (->> (b x)))
=> (->> a (b x))
=> (b x a)
defn title-case [xs]
do you think there is something more idiomatic that xs for the argument name?
bbatsov's Clojure style guide (https://github.com/bbatsov/clojure-style-guide#idiomatic-names) treats this.
and (-> a (->> (b x) (c y)))
produces (c y (b x a))
@zcassini since the argument is a string, I’d just use s
i guess that makes sense, cause its not quite a list of chars or at least it is a special case
@teodorlu Yes, macros are “just” functions of code that produce code so the outer ->
rewrites its arguments first, then there’s another pass since there are still macros present (`->>`) and so more macro-expansion happens.
@seancorfield That makes a lot of sense. Thank you.
The biggest difference between macros and (regular) functions is that the latter have their arguments evaluated before the call whereas the former do not.