This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-23
Channels
- # aws-lambda (5)
- # beginners (212)
- # boot (3)
- # cider (130)
- # cljs-dev (24)
- # clojars (2)
- # clojure (287)
- # clojure-dusseldorf (23)
- # clojure-italy (11)
- # clojure-russia (10)
- # clojure-spec (9)
- # clojure-uk (45)
- # clojurescript (59)
- # core-async (1)
- # cursive (13)
- # datascript (1)
- # datomic (46)
- # emacs (12)
- # events (9)
- # fulcro (196)
- # graphql (3)
- # hoplon (79)
- # jobs (5)
- # jobs-discuss (7)
- # jobs-rus (2)
- # keechma (26)
- # keyboards (9)
- # leiningen (2)
- # luminus (9)
- # off-topic (20)
- # om-next (1)
- # onyx (15)
- # re-frame (16)
- # reagent (18)
- # reitit (1)
- # remote-jobs (2)
- # rum (3)
- # shadow-cljs (13)
- # sql (135)
- # unrepl (46)
- # vim (1)
- # yada (23)
i'm trying to model a singly linked list. I don't think hash maps will work because i want to allow same-valued nodes. what about a record?
in python i'd use a class, and as far as i can tell the simplest "class"-like thing in clojure is a record
list and lazy-seq are already singly linked lists, I don't know why you would use a hash-map, how is that useful when each node has exactly one successor?
if you want to make a singly linked list in clojure and not use a list or lazy-seq (or something from java.util.Collection), the easiest thing is {:value foo :next bar}
where bar is another hash with the same keys, or nil
what would node.next look like if i used a list?
(next l)
in fact, there's a next method too
user=> (.next (list 1 2 3))
(2 3)
but it's better to use the next function, as it knows how to handle other types, and it's a first class value
looks like that would work great
but part of the exercise is deliberately using a more primitive data type, perhaps
function instead of method
user=> (next (list 1 2 3))
(2 3)
where you're handling the nodes and nothing else, if that makes sense
sure - then you can use (:next l) if l is the hash map I initially proposed
thank you!
when would you use a record over a hash map?
+user=> (defn construct [x y] {:val x :next y})
#'user/construct
+user=> (construct 1 (construct 2 (construct 3 nil)))
{:val 1, :next {:val 2, :next {:val 3, :next nil}}}
+user=> (def ls *1)
#'user/ls
+user=> (:next ls)
{:val 2, :next {:val 3, :next nil}}
+user=> (:next (:next ls))
{:val 3, :next nil}
generally you would use a record if you need to implement a protocol or interface - if you have methods you need to overload
ok, that makes sense.
am i right in thinking the above example doesn't implement a protocol/interface that hash-map doesn't already have?
right - it literally is a hash-map
if you wanted it to print like a list, or be accepted by all the standard list functions, then you'd want to implement the Interfaces that define a clojure list
:thumbsup:
Im trying to build a simple rest-api with Luminus. just playing. would like to expose the guestbook as a json api. been googling for a while now and i still cant find a simple example for returning basic json data like array or simple objects from a given db query
@michael740 if you wanted to also make sure it wasn't a hash-map and couldn't be used that way, there's also deftype
good to know.
@jstuartmilne there's a wrap-json middleware that can take a request handler function and return a new one that makes json - then you just return your data structure
@jstuartmilne any standard clojure binding for a database should hand you plain data structures as a result, then it's just a question of making the transforamtions (if any) needed to construct the data your client should expect
thank u @noisesmith I kind of got the theory behind it, just couldnt mange to find an example.
it's literally (wrap-json-body f)
- https://github.com/ring-clojure/ring-json#wrap-json-body
where f is a function that takes a request and returns some data
np - I think the example in those docs should be enough to start with - though I understand if you haven't used ring much yet you'll want to play with the request and see what's in it
the good news is it's a hash-map, you can print it, look at the keys, use standard clojure data functions on it
ring is an exemplary clojure library in that it eliminates a lot of unneeded complexity to just let you use data
yeah i was going through the Luminus docks. and the documentation specifies By default, muuntaja middleware library is used to infer the response type when a route returns a map containing the:body key:
interesting - what did you try putting under that key? and what would it use to infer by?
or at least thats my understanding. Im surprised i could not find an example for a simple CRUD
(GET "/message" []
:return []
:summary "x^y with header-parameters"
(ok (db/get-messages)))
OK - looking at the muuntaja repo, it looks like it adds the right headers if your :body contains a string that looks like json?
oh, you have to explicitly call muuntaja's encode function if it is using that
but what I don't understand is what tells it "make this json"
anyway, looks like there's docs at the muuntaja repo https://github.com/metosin/muuntaja/wiki/With-Ring (edited for better example)
@noisesmith thank u got it
i'm trying to translate a simple tail call recursion into loop...recur
(defn reverse_l
[list_]
(if-not (seq list_)
list_
(concat (reverse_l (rest list_))
(list (first list_)))))
am i correct in thinking my call to reverse_l
is not in the tail position?
and therefore i'd need to rework it into something fundamentally not recursive
yeah, it throws a compiler exception right away.
or rather, this does:
(defn reverse-l
[l]
(loop [l l]
(if-not (seq l) l
(concat (recur (rest l))
(list (first l))))))
it can be recursive, but there are many options for recursion because of the limits of the JVM
in order to make reverse tail recursive, you need an extra argument representing the already-reversed
and then you are putting data into that, instead of the stack
(reverse-l (rest l))
?
@michael740 to make it tail recursive it needs at least two args
so you end up with more convoluted code, and a helper function
hmm. i thought loop
was sort of the iterator?
if you work out on paper what the function is doing, you'll find that you need two accumulators as it recurs - you can't represent everything in one argument
loop is a target for recur - it's basically a goto label plus argument bindings
you need two bindings in the loop
if you want to tail call with recur, you can define a local fn that takes the extra arguments
@lockdown- loop takes as many args as you like, there's no need for a local function
oh. the extra arg you're talking about is the accumulation?
the essential thing here is to recursively reverse an argument and not consume stack, you need to track two things - unprocessed items, and processed items
@noisesmith yeah, I said that because he can still make his main function take just argument (more elegant I think in this case) and inner function that recurs use the other args
ok, this gets me on the right track... i'll work it out š
@lockdown- right and what I'm saying is that loop takes as many args as you need, and that's the reason you use it instead of recur to the function itself (also a valid target for recur)
yes, we have to assume that what @michael740 is doing here is an exercise, the existing clojure.core/reverse does use the sequence abstraction (implicitly via reduce1)
the code is quite elegant for those who aren't doing this exercise by the way, figuring out why it works can be enlightening (and I'll spoil it a bit by saying it does use a two argument function but ... not exactly the way I am suggesting at first glance)
(defn reverse-l
[l]
(loop [to-reverse l
reversed (list)]
(if-not
(seq to-reverse)
reversed
(recur (rest to-reverse)
(concat
(list (first to-reverse))
reversed)))))
@noisesmith good point
@michael740 check this out
user=> (source reverse)
(defn reverse
"Returns a seq of the items in coll in reverse order. Not lazy."
{:added "1.0"
:static true}
[coll]
(reduce1 conj () coll))
how do i see the source code for reduce1
?
for now you can mostly ignore reduce1 and just look at reduce - it's defined in clojure's java code iirc
oh - reduce isn't much helpful - it just invokes .reduce method or coll-reduce in clojure.core.protocols
so yeah, both are in the java code - they are folds if that helps
i have a little experience looking at folds in SICP. i remember they can often reverse collections
maybe that's the intuition you were getting at?
that's part of it yes - a reduce can be treated as a loop that always has 1 accumulator for an arbitrary value, and one loop binding that represents "the next item" - it returns the last value of that accumulator when it gets done with the last item
@michael740 a very simple improvement you can use with your existing code is use (cons (first to-reverse) reversed)
to replace your usage of concat
just wanted to point out that there are many ways to recur in clojure because of the jvm can't optimize direct recursion, and choosing which one is the aproppiate one is not that easy at the beginning, there to many variables to have in mind
@lockdown- can you say more?
cons
works in "reverse" order??
equivalent is (conj reversed (first to-reverse))
compared to conj, yes, it's opposite order
user> (cons 1 (list 2 3))
(1 2 3)
your suggestion works but i don't see how
cons puts the first arg in the head position. i want (first to-reverse)
last
(cons x l)
and (concat (list x) l)
do the same thing - except cons does it more directly
no - you want it at the current head, the same way you were putting it with concat
if you add a println that shows each item you process and the current value of what you have processed so far, I think you'll see how it works
oh. ok. i think i was still thinking about the simpler, recursively-defined function.
where you do indeed want to return something like (cons (reversed (cdr l)) (car l))
cons has args in the opposite order though
the second arg to cons must be a collection or nil (treated as equivalent to ())
yes, that's right.
@noisesmith in the wild, is trampoline or leftfn used much?
not as often as you might expect - they are pretty niche tools but very handy when you need them
and often they work well together
(since you want to be able to refer to other steps mutually in mutual recursion)
@noisesmith by working together you mean using trampoline inside a letfn?
I mean the should be able to return each other in order to trampoline (or use each others in partials as the case may be)
this can also be done with declare, or by passing one function to the other, but it can simplify things to use letfn
it creates functions, those functions use stack, yes
Hello, could smbd please explain why in one case
(take 5 (map prn (range 10)))
REPL prints 10 numbers & in other case
(transduce (comp (take 5)
(map prn))
conj
[]
(range 10))
it prints only 5 but we have take 5
in both examples?I believe the first example prints 10 because of chunking. The latter doesn't chunk.
does prn
cause side effects?
both map
and range
are supposed to return lazy sequences
@janis.urbis are you referring to this blog post? https://stuartsierra.com/2015/08/25/clojure-donts-lazy-effects
seems like the short answer is something like, lazy-sequences and side effects don't mix?
@michael740 yes, to that post
@michael740 š Yes, I got that from the article. Currently trying to understand trasreducers better. Thank you for your response)
i hope you get a more detailed explanation. i'd be curious to know, too
For those who use compojure-api (directly or via Luminus), there is a
namespace in the 2.0.0-version. Works like this:
(require '[ :as help])
(help/help)
;; all topics
(help/help :meta)
;; all registered handlers
(help/help :meta :path-params)
;; help on :path-params
the last on prints (with nice colors ;)):
:path-params
path-params with letk. Schema is used for both coercion and api-docs.
(POST "/math/:x/:y" []
:path-params [x :- s/Int, {y :- s/Int 1}]
(ok {:total (+ x y)}))
hi there. how do I figure out how to integrate a flatpickr datetime-picker (https://clojars.org/cljsjs/flatpickr) in my reagent form? I don't get how to call the flatpickr. Any help much appreciated!
clojars question. š i have a client/server project that i'm deploying to clojars via lein deploy clojars
. :prep-tasks
takes care of the clojurescript compilation, css is processed, etc. but when i inspect the jar that comes down from clojars it only has some content in the /public
dir. most importantly it's missing my compiled javascript. any thoughts?
I successfully wrote a type that prints out its content, based on bits I found in the source code of clojure.core
. However, I don't fully understand the code I typed:
(deftype Node [graph id]
IPrintWithWriter
(-pr-writer [this writer opts] (-write writer (str id))))
What is that -write
function, and does the -
prefix have a special meaning?@vincent.cantin thatās cljs not clj
yes, you are right
-
doesnāt have any special meaning, but itās idiomatic to prefix a protocol method with -
and then wrap it in a regular function
oh, I got it! It is defined there https://github.com/clojure/clojurescript/blob/r1.9.946-22-gebdaf6c/src/main/cljs/cljs/core.cljs#L741
Hello, maybe somebody created here osx app based on java. I need to use java to access native things. The jar run fully normal with ālein runā but when I deployed with javapackager.. and start the application .. I got āapplication need to accept incoming network connectionsā. I read many java forum now.. somebody can help me, who solved this problem?
If I understand correctly, your app is not using the network and you want to avoid this message. Isn't it?
Maybe try to ask on StackOverflow.
Yes, that is the problem. I used my application as a local server and therefore I have incoming network connections.
I read about in java forums maybe that can solve with SocketLock or else.. but I donāt understand fully.
Yes, I will drop to Stackoverflow. thx! @vincent.cantin
I found out.. I signed the pkg.. but something not correct and in this case: āSuch errors usually indicate broken application signature.ā
Just accept in the security settings of OSX.
That's an OSX issue, mainly.
Where is the best place to go to learn clojure? Iām coming from java and Iāve been struggling with learning clojure for the last 2 weeks. Iām finding the reason Iām struggling is because I donāt understand the language and some of itās basics. Itās hard for me to understand a lot of the clojure docs as well. Are there any books, websites, articles, etc⦠you guys recommend to help me get up to speed?
Have you tried http://purelyfunctional.tv? Eric is great in breaking the basics into digestible pieces. After trying books and tutorials, I've found his videos to work best for me.
also I liked this just for puzzle practice http://clojurescriptkoans.com/
Living Clojure or Clojure for the brave and true. Both have a different style. If your looking for a more nuts and bolts approach, Joy of Clojure.
if you're willing to purchase pragprog has a book written written by alex miller and stu halloway. i've purchased it for myself and a coworker based on how much i enjoyed it. definitely worth the purchase price https://pragprog.com/book/shcloj3/programming-clojure-third-edition
I started with clojure for the brave and true. That fact that it was free online was great - and so I went and bought it!
Also, if youāve done https://www.codewars.com/ , clojure is one of the languages. It can be interesting to solve a kata in, say, java, then try it again in clojure, then once youāve solved it, compare your solution to others and say, āOh, ok, I didnāt know that was a thing.ā
https://aphyr.com/tags/Clojure-from-the-ground-up these articles are also pretty good
i also found reading through all the stuff on https://clojure.org great
oh! of course! there is this series too: https://www.youtube.com/watch?v=P76Vbsk_3J0, by rich hickey, the designer of clojure
there are also challanges at http://www.4clojure.com
vectors are very close - O(log32(n)) iirc
they have to get very large before the difference between that and O(1) is likely to matter
if a vector isn't fast enough, us an array
right
but do profile - it's very likely that indexed lookup is not your bottleneck
yourkit
you can get a free license for open source use yes
Any thoughts or recommendations on an editor/IDE for Clojure? Using NightCode and Atom with some REPL support. But both are not really it. Emacs is just too intimidating⦠I do use VIM occasionally, but it seems a hassle to set upā¦
the vim setup was much easier than cider for emacs was fwiw, it's just a language mode and then optionally a lispy editing mode (I like vim-sexp) and finally fireplace if you want repl integration - fireplace is trivial to set up
I would highly recommend giving Spacemacs a try. I am a complete Emacs newbie, and after 4-5 months, I am the most productive I have ever been in any IDE/language setup
spacemacs is good but the repl kept getting in my way, I had a better time using vim + fireplace, the vim-sexp is cool and the vim-sexp-mappings-for-regular-people makes editing a breeze
spacemacs is indeed powerful but I kept getting the impression that some things were off the place
@jeroen.leenarts Is there something specific you don't like about Atom/ProtoREPL? That's what I use (I switched from Emacs).
@jeroen.leenarts if you want to avoid setup hassle, check out http://lighttable.com/
@jeroen845 Still a bit intimidating - but a lot of clojure dev are likely http://spacemacs.org/ - and very little additional setup needed from defaults.
And https://medium.com/@jacekschae/slick-clojure-editor-setup-with-atom-a3c1b528b722?__s=yhkji5g2isqeq4iwkasz - steps you thru Atom setup for clojure dev.
@jeroen.leenarts there's also a clojure extension for Visual Studio Code (great editor, haven't tried the extension though)
@jeroen.leenarts You only have to set it up once per machine and the "opinionated guide" is pretty straightforward š
About a month ago I tried every option available. Vscode, atom, emacs and cursive. Iād suggest emacs with cider or cursive. Spacemacs is free and easy to install and require a little configuration. Cursive is free for studying :)
(my usual suggestion is "whatever editor you're already using" with some sort of Clojure plugin to hook into a REPL)
That last medium link seems to have worked for me⦠Trying atom with basic repl support now. Works much better then the āopiniated guide I used beforeā.
I regularly try out a bunch of IDEs and I almost always go back to Spacemacs + CIDER. Although I donāt think Spacemacs is substantially greater than any other editor. I feel like they all have certain limitations that can be annoying for certain use-cases (e.g., lack of extract-function in cursive, lack of static analysis in spacemacs ā but also some static analysis can be annoying when using certain macros; such as Clara Rules rules/queries)
Really looks interesting⦠Emacs for my VIM fingers⦠Only problem is that their install from scratch is currently broken⦠Just my luck⦠š https://github.com/syl20bnr/spacemacs/issues/10244
They are migrating from the standard melpa package repository to their own āspacemelpaā repository.
@U7V9HE682 Any reference on that I can keep an eye on?
Really looks interesting⦠Emacs for my VIM fingers⦠Only problem is that their install from scratch is currently broken⦠Just my luck⦠š https://github.com/syl20bnr/spacemacs/issues/10244