This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-03-01
Channels
- # aleph (4)
- # arachne (24)
- # beginners (231)
- # boot (4)
- # cider (63)
- # clara (36)
- # cljs-dev (57)
- # clojure (195)
- # clojure-dev (12)
- # clojure-gamedev (2)
- # clojure-greece (1)
- # clojure-italy (10)
- # clojure-poland (4)
- # clojure-spec (36)
- # clojure-uk (65)
- # clojurescript (133)
- # core-async (8)
- # core-logic (2)
- # cursive (18)
- # data-science (3)
- # datomic (58)
- # defnpodcast (3)
- # duct (2)
- # emacs (2)
- # fulcro (27)
- # graphql (3)
- # hoplon (18)
- # jobs (2)
- # jobs-discuss (10)
- # jobs-rus (1)
- # lumo (1)
- # mount (6)
- # nyc (2)
- # off-topic (27)
- # pedestal (13)
- # re-frame (71)
- # reagent (105)
- # reitit (4)
- # ring (2)
- # ring-swagger (1)
- # rum (10)
- # shadow-cljs (172)
- # spacemacs (24)
- # sql (26)
- # tools-deps (1)
- # uncomplicate (4)
- # unrepl (51)
- # vim (3)
- # yada (11)
more generally, the idea that you can think of functions as values at all, which is a hallmark of “functional” languages
is both treating double
as a value (because I can call prn
on it) and a function (because I can call it on 4)
@suryapjr for example, in java the method foo when you call Bar.foo() is not first class - you can't do anything with .foo itself, you can't pass it to another method or store it for later
(there are reified reflective objects that "represent" a method but that's a whole other thing and not what people are typically using)
a clojure function is an object, so you can pass it as an argument, store it, return it, etc. etc. etc.
As far as I know, your options are largely either running a socket that your python code can call, or hosting a python interpreter like Jython in the JVM and using interop.
@noisesmith thanks !
@suryapjr inside the running repl you can run (load-file "/home/src/core.clj")
if you need to require other files you'll also need to set the proper classpath on jvm startup
@noisesmith cool..how do i run the main function
once you have loaded the file into the repl you can run it by the full namespaced name - or if you don't have an ns form in the file, just run it directly because it was defined in your current ns
OK - so call it by the full name, if it's called main and is in foo.bar ns, call (foo.bar/main)
CompilerException java.lang.RuntimeException: No such var: name/main, compiling:(NO_SOURCE_PATH:5:1)
My core.clj:
(ns name)
(defn -main []
(println "Whats your name ?")
(def name read-line)
(str "Hi " "" name) )
then call (name/-main)
it's not called main, it's called -main
yeah, jars are the normal way. But for others to use it, be sure you don't have a single segment namespace - make sure it has a meaningful ns with more than one part
and also put it in a path that is relative to the ns
yes, that's the easy way to make a jar, but so far pooboy was explicit about how to do things without lein
pooboy yeah - using the jar command line program - you can find out how to use that via google or the manual page, I have only used it minimally myself
also most pople use their jars via maven, which gets more complicated and you start to see why people use leiningen
maven requires certain conventions be followed, specific documents and formats and folders in the jar etc.
it's refreshing to answer "how to do this with the simplest tools" rather than "what's the easy way" once in a while, heh
And in the below code .. My core.clj:
(ns name)
(defn -main []
(println "Whats your name ?")
(def name read-line)
(str "Hi " "" name) )
When i run it .. i get .. user=> (name/-main) Whats your name ? "Hi clojure.core$read_line@19321e2" user=> ( def x read-line) #'user/x user=> x #object[clojure.core$read_line 0x19321e2 "clojure.core$read_line@19321e2"]
because read-line is a function, and functions are values
to call functions, you need parens
also, as an aside, def creates globals, it's OK for simple learning examples but breaks easily in real code - for local values there's let
@suryapjr to be clear read-line
is just a function (it has a weird name with a @ and number in it), (read-line)
actually calls the function
Ohh..cool @noisesmith
I am about to go take a bus home, I'm sure other people can help
(ns name)
(defn -main []
(println "Whats your name")
(def name (read-line))
(str "Hi " "" name)
)
@suryapjr If you revise your code to use let
instead of def
it would look like this
(defn -main []
(println "Whats your name ?")
(let [name (read-line)]
(str "Hi " "" name)))
I implemented A* algorithm to solve the n-puzzle problem. It works for 3x3 puzzles fine. However, when I try to solve a shuffled 4x4 puzzle, the browser runs out of memory. Here’s the core A* functions:
(defn- make-mm [vals]
(into (sorted-map)
(into []
(map #(vec [(first %) (set (rest %))]) vals))))
(defn- A* [open closed dim]
(when (not (empty? open))
(let [[key node] (first-multi open)
puzzle (first node)]
[key node]
(if (solved? (first node))
(reverse (create-path node []))
(let [open (dissoc-multi open (nth node 3) node)
closed (conj closed puzzle)
neighbors (get-neighbors puzzle dim)]
(recur
(reduce
(fn [coll neighbor]
(let [g (+ 1 (nth node 2))
f (+ g (heuristic neighbor dim))]
(assoc-multi coll f [neighbor node g f])))
open
(map #(when (nil? (get closed %)) %)
neighbors))
closed
dim))))))
(defn solve [start dim]
(let [closed #{}
f-start (heuristic start dim)
open (make-mm [[f-start [start nil 0 f-start]]])]
(if-let [path (A* open closed dim)]
(let [p1 (vec path)
p2 (into [(first p1)] (pop p1))]
(rest (map #(get %2 (.indexOf %1 0)) p2 p1))))))
(Full code can be found here: https://github.com/nakiya/npuzzle/blob/master/src/cljs/npuzzle/db.cljs)
So when call (solve [5 1 4 6 7 3 8 2 0] 3)
, it returns (2 7 6 5 1 4 3 6 7 8 5 7 4 3 6 2 8 4 2 6 3 2 7 5 4 7 5 4 7 8)
which are the tiles needed to be moved to get to goal position.
What can I do to reduce memory usage?
P.S. Of course, I can put the A* algorithm on server side. But I am asking about the general code here. I am new at clojure, so I want to know if I’m doing anything wrong.The app is here: https://n-block-puzzle.herokuapp.com/
A consequence, though, is that each time you run the function, if you are using def
it redefines a name
var:
name=> (-main)
Whats your name
Mike
"Hi Mike"
name=> name
"Mike"
name=> (-main)
Whats your name
Surya
"Hi Surya"
name=> name
"Surya"
hey all, I'm having trouble using a nodejs library in a clojurescript project using leiningen
but I get this error:
Caused by: clojure.lang.ExceptionInfo: No such namespace: twit, could not locate twit.cljs, twit.cljc, or Closure namespace "twit" in file src/twitter_unfollower/core.cljs {:tag :cljs/analysis-error}
I've tried adding it to my project.clj
(defproject twitter-unfollower "0.1.0-SNAPSHOT"
:description "Jim's bot"
:url ""
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.8.51"]
[org.clojure/core.async "0.2.395"]
[io.nervous/cljs-lambda "0.3.5"]
[cljs-http "0.1.44"]]
:plugins [[lein-cljsbuild "1.1.4"]
[lein-npm "0.6.0"]
[lein-doo "0.1.7"]
[io.nervous/lein-cljs-lambda "0.6.6"]]
:npm {:dependencies [[source-map-support "0.4.0"]
[xhr2 "0.1.4"]
[twit "2.2.9"]
]}
:source-paths ["src"]
:cljs-lambda
{:defaults {:role "arn:aws:iam::954459734159:role/cljs-lambda-default"}
:resource-dirs ["static"]
:functions
[{:name "cljs-twitter-unfollower"
:invoke twitter-unfollower.core/run-lambda}]}
:cljsbuild
{:builds [{:id "twitter-unfollower"
:source-paths ["src"]
:compiler {:output-to "target/twitter-unfollower/twitter_unfollower.js"
:output-dir "target/twitter-unfollower"
:source-map true
:target :nodejs
:language-in :ecmascript5
:optimizations :none}}
{:id "twitter-unfollower-test"
:source-paths ["src" "test"]
:compiler {:output-to "target/twitter-unfollower-test/twitter_unfollower.js"
:output-dir "target/twitter-unfollower-test"
:target :nodejs
:language-in :ecmascript5
:optimizations :none
:main twitter-unfollower.test-runner
:npm-deps { :twit "2.2.9" }
:install-deps true}}]})
is there something else I'm missing?
I try to require it like a normal namespace
(ns twitter-unfollower.core
(:require [cljs-lambda.util :as lambda]
[cljs-lambda.context :as ctx]
[cljs-lambda.macros :refer-macros [deflambda]]
[cljs-http.client :as http]
[cljs.nodejs :as nodejs]
[cljs.core.async :as async :refer [<!]]
[twit :as twit])
(:require-macros [cljs.core.async.macros :refer [go]]))
@derpocious My only comment is that many developers are transitioning to using the new NPM dependencies capability built directly into ClojureScript 1.9.946
thanks 🙂
I would really like to be able to use it in this 1.8 project though
out of curiosity, are there any good articles on the new way?
@derpocious https://clojurescript.org/news/2017-07-12-clojurescript-is-not-an-island-integrating-node-modules
thanks, I've read that article and added the :npm-deps, but I'm getting the same error 😕
I also found this nice clojure twitter api https://github.com/adamwynne/twitter-api, but it is not cljs so I don't think I can use it 😕
Very strange. I just tried adding another node library with [node-twitter "0.5.3"]
When I add that only to the project.clj :npm { :dependecies it does compile fine, and I even see the node package being downloaded in the console
but then when I try to require the namespace in my code it says it can't find the namespace 'node-twitter'
Is there a shorter or a more elegant way to do this?
(reduce #(if (even? %2) (assoc %1 %2 (+ %2 50)) %1) {} [1 2 3 4 5])
--> {2 52, 4 54}
Basically, I’m interested in the form:
(reduce #(if <condition> (assoc %1 %2 <calculation> %1) {} <collection>)
clojure itself isn't that great for it due to it's long startup time. It can be used though, just build an uberjar and then execute it. However, you can use ClojureScript for this via lumo https://github.com/anmonteiro/lumo
both calls end up into different function body where you can do different things if you so choose
which will print "Hello, World" when called without arguments (hello)
but you can call it also with an argument like (hello "Slack")
which would print "Hello, Slack"
first you learn to not see the parenthesis, then you learn to love them and after that no other syntax makes any sense anymore
see: https://clojure.org/about/lisp https://www.braveclojure.com/read-and-eval/ https://aphyr.com/posts/305-clojure-from-the-ground-up-macros
something like that
Uncaught TypeError: xK is not a function
at app.js:1227
at app.js:1334
ns fun)
(defn -main []
(println "Hello")
(println "What do u want to add to your list? ")
(def item (read-line))
(def mylist '())
(conj mylist item)
(println mylist))
This code gives me the below output user=> (load-file "core.clj") #'fun/-main user=> (fun/-main) Hello What do u want to add to your list? egg () nil user=>
because clojure is a functional language, you can't "change" mylist
. try (println (conj mylist item))
using def
to hold changing values is not a good practice, btw. look for atom
a quick example of what I mean
user=> (def item (atom nil))
#'user/item
user=> (reset! item (read-line))
Hi!
"Hi!"
user=> (def mylist [])
#'user/mylist
user=> (println (conj mylist @item))
[Hi!]
nil
user=>
@suryapjr This is more of a imperative style of writing code. In term of statements; which inherently use state. I would suggest seeing https://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey to get the whole Functional style of thinking. Would be helpful in learning Idiomatic Clojure and FP
Thanks !! @joelsanchez @rahul080327
For me seeing this before learning Clojure helped a lot 🙂
@rahul080327 thanks bud !!
def
defines a globally-available var at the top level of a namespace. let
defines a local constant that can only be used inside its body
user=> (def a 1)
#'user/a
user=> a
1
user=> ((fn [] a))
1
user=> (let [a 2] a)
2
user=> a
1
user=> ((fn [] a))
1
https://clojure.org/reference/special_forms#def https://clojure.org/reference/special_forms#let
@joelsanchez..what is an atom
docs https://clojure.org/reference/atoms* examples https://clojuredocs.org/clojure.core/atom basically a reference to a value, which you can update in a thread-safe way ("atomically")
Hi again! When using cljsjs-packages, do I need to add their externs in the uberjar-profile in my luminus-project?
Hi everyone, is there a function or a library already exists to insert something on every nth entry in collection? Something like
(insert-nth 2 [1 2 3 4] "hello")
=> [1 2 "hello" 3 4 "hello"]
(let [n 2
xs [1 2 3 4]
in "hello"]
(into []
(comp (partition-all n)
(mapcat #(conj % in)))
xs))
I've seen the documentation on into
, I can't really understand what the xform
part does? Could you explain it to me @rauh?
(into [] (comp (partition-all n) (mapcat f)) coll)
is equivalent to (into [] (->> coll (partition-all n) (mapcat f))
but is more efficient since it does all of the transformations in a single step (no intermediate collections are generated)
Why does the equivalent is partition-all
being used first? If I evaluate ((comp str inc) 4)
it returns "5" instead of an error, meaning that 4 is applied to inc
first then str
right?
comp
always composes the functions passed in from right to left (transducers are functions). it's just that transducers have functions nested in functions, and due to the way those nested functions specifically work, they actually end up applied from left to right
https://www.youtube.com/watch?v=WkHdqg_DBBs&list=PLhi8pL3xn1OTfhjnIHmokYjKzLSBtYu8- i found these videos helpful in understanding them
ah, i seems there's only one still on there. you can find the rest here if you want: https://tbaldridge.pivotshare.com/categories/transducers/2426/media
https://www.youtube.com/watch?v=6mTbuzafcII this talk uses a real-world metaphor to explain them, if you find that more helpful than seeing code
@hawari.rahman17 And if n
is small you could get away with something like
(let [xs [1 2 3 4]]
(interleave (take-nth 2 xs) (take-nth 2 (rest xs)) (repeat "hello")))
@mfikes here's the 'alternative' version i came up with: (apply concat (interleave (partition 2 [1 2 3 4]) (repeat ["hello"])))
It feels like interleave
is fairly close to the original question, and when composed with partition
you can arrive at a solution
yeah, though with partition-all
you end up with an extra "hello" if the input is too long, and with partition
you end up with the remainder being swallowed
@sundarj I just realized your solution can be golfed a litter further with flatten
, which is getting pretty succinct 🙂
(flatten (interleave (partition 2 [1 2 3 4]) (repeat "hello")))
Summarizing, this solution is appealing because it is easy to read, while I bet the solution given by @rauh is much more efficient.
For a fair comparison with his solution:
(let [n 2
xs [1 2 3 4]
in "hello"]
(flatten (interleave (partition n xs) (repeat in))))
simple-benchmark
in Planck and Lumo show Rauh's running in 2/3 the time as the flatten
approach in JavaScriptCore, but 3 times in V8. Hrm. I guess YMMV.
Sorry for replying so late, and wow, I didn't expect for people to be so thoroughly helpful on my question. You guys really are awesome!
Hey peeps, I'm in the process of setting emacs up for Clojure. I'm coming from Dr.Racket and there new lines get automatically indented when inside brackets. In emacs not, unless I press tab or C-I.
@nikoszp There is probably a couple ways to handle parens. * paredit * parinfer are two that come to mind. I’m not sure how to autoformat in emacs off the top of my head.
@mfikes the one thing about flatten is that it doesn't respect your input datatype, in most cases it can be replaced with apply concat (which also will perform better) - or a cat transducer
or even mapcat
I've been fiddling with the "Clojure indent style" in the customization buffer but it doesn't seem to change anything. Thanks @drewverlee I'll have a look.
@nikoszp @drewverlee for making things indent properly, there's something like electric return that makes newline indent properly
I've had extremely poor experiences with co-workers abusing parinfer and I'd even advise counting parens by hand before considering parinfer
i haven't touched parinfer/paredit yet. most people seem to recommend parinfer for newbies, do you instead recommend paredit?
yes, paredit, and/or rainbow-parens
the bad thing with parinfer is that with a shared code base, someone can accidentally check in weird indentation (it happens...) and then parinfer user loads the file and makes all the parens move to match indent which - always breaks everything
I believe that problem is fixed in new versions.
Which aren’t on emacs -_-
that would be nice - FWIW I don't htink it was a parinfer bug, it was a user workflow bug (maybe?) anyway the fact that parinfer makes things like that easy is frustrating
also the fact that people just check files into git without doing a diff by diff audit of what they are checking in
CO WORKERS ARE TRYING TO MAKE ME DIE YOUNG
Yea. that problem sort of exists in every ecosystem to some extent. I think that structurl changes > parinfer as well. But its a bit of a mental leap that i’m not ready to invest in at this stage. e.g i’m not going to stop what i’m doing to figure out what combo of slurps and barfs i need…
i suppose the fact parinfer does paren-matching implicitly means it's bound to cause issues like that
On this topic, i wouldn’t let great be the enemy of good. If your used to ruby and python which put a heavy emphasis on indentation, then using parnifer sort of naturally does what you want.
I dont have co-workers using clojure.
right, just don't check garbage changes in to code others have to deal with :P
Noisesmith, is there anything substianantly better then paredit for emacs?
not sure? I had to flee emacs after over a decade of usage, I'm a vim user now
In theory you could add a formatting check in your CI, e.g. load the file in an offline emacs session with parinfer mode and watch what happens. If parinfer wants to move any parens then abort the build. That may feel heavy-handed, but not unprecedented.
there’s also cljfmt check
which is actually designed for showing you if formatting is bad
Right. Could there be corner cases where parinfer and cljfmt disagree? I have no idea.
@noisesmith It's working! Thank you!!
How would I convert a sequence to a vector so I can call mapv
on it? I tried this but it didnt work (mapv :a (into [] (-> checks (into {}))))
note that (-> checks (into {}))
is (into checks {})
which doesn't seem to do a lot of good
play in the repl a lot. use doc
and source
. and run experiments on vectors like [:a :b :c]
I have what I think is a sequence of vectors of maps which I can’t figure out how to turn into a vector of maps
user=> (reduce (partial reduce conj) [] '([{}] [{}]))
[{} {}]
user=> (into [] cat '([{}] [{}]))
[{} {}]
From this server:
(ns npuzzle.handler
(:require [compojure.core :refer [GET POST defroutes]]
[compojure.route :refer [resources]]
[ring.util.response :refer [resource-response response not-found]]
[ring.middleware.reload :refer [wrap-reload]]
[ring.middleware.json :refer [wrap-json-response wrap-json-body wrap-json-params]]
[ring.middleware.keyword-params :refer [wrap-keyword-params]]))
(defroutes routes
(GET "/" [] (resource-response "index.html" {:root "public"}))
(POST "/ajax/:params" [params] (println params))
(resources "/"))
(def handler (-> #'routes wrap-json-response wrap-json-params (wrap-json-body {:keywords? true})))
I get the below error when /ajax
is POSTed to with {:puzzle [7 5 3 2 4 8 0 1 6]}
as payload:
java.lang.IllegalArgumentException: Cannot open <{:puzzle [7 5 3 2 4 8 0 1 6]}> as an InputStream.
Can someone help me understand what’s going on?I have values that will always be in one order. I'm looking to turn them into a map. This works (apply assoc (conj (interleave [:a :b] [1 2]) {}))
but I'm betting there's something more idiomatic. Any suggestions?
(into {} (map vector [:a :b] [1 2])) - this is idiomatic, and performs better
the standard idiom is the one noisesmith posted above. or at least that's what i've seen the most and is easily recognized by me. others might vary. but i do think a standard pattern is more idiomatic than a function that does exactly what you are looking for
Ah I know what you mean - like somebody using not-empty
instead of seq
because it’s better aligned with the intent
sorta. idiom to me is just common patter. it's easy to write correct code that just doesn't look like what most people write is all. its not better or worse. think "pythonic".
(-> thing :a :b)
vs (get-in thing [:a :b])
. one does exactly what you need. one is more general but seen quite a bit more i think
yeah I just forgot about zipmap (I rarely need it) so I just showed the pattern I use for stuff like that
agreed zipmap is common and the right thing to use