This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-03-16
Channels
- # atlanta-clojurians (8)
- # beginners (103)
- # boot (22)
- # boot-dev (1)
- # cider (36)
- # cljs-dev (55)
- # cljsrn (3)
- # clojars (25)
- # clojure (104)
- # clojure-brasil (1)
- # clojure-dusseldorf (2)
- # clojure-italy (8)
- # clojure-norway (9)
- # clojure-russia (15)
- # clojure-spec (6)
- # clojure-uk (26)
- # clojurescript (246)
- # cursive (26)
- # data-science (1)
- # datomic (22)
- # dirac (11)
- # editors (1)
- # emacs (8)
- # fulcro (50)
- # graphql (11)
- # hoplon (1)
- # jobs-discuss (27)
- # leiningen (44)
- # luminus (33)
- # lumo (2)
- # mount (1)
- # off-topic (8)
- # onyx (5)
- # parinfer (4)
- # reagent (94)
- # ring-swagger (14)
- # shadow-cljs (37)
- # spacemacs (10)
- # specter (3)
- # tools-deps (4)
- # unrepl (14)
- # yada (5)
hey guys, I JUST started clojure as my first function language
can a good soul explain me why my fibonnaci works?
(defn fibIterative
[x]
(if (= x 0) 0)
(if (= x 1) 1)
(loop [i 0, x1 1, fib 0, x0 0]
(when (<= i x)
(recur (+ i 1) (+ x1 x0) (+ x1 x0) (- x1 x0))
))
)
I never return fib, how does it work haha
those ifs do nothing
and when returns nil if the condition is false - so when it stops looping, it returns nil
nil? it is returning the proper value here, when x = 10, it returns 55
I don't see how that code could do that
can I add an else to when?
when either evaluates its body (here a recur), or returns nil
you can add an else to if
perhaps you want cond instead of the ifs and the when
(cond (= x 0) 0 (= x 1) 1 :else ...)
makes sense, but why do you say the ifs do nothing?
if x equals 0 for example, it should return 0 right?
because nothing uses their value
they return, and are ignored
@brnbraga95: in clojure forms have values, and if nothing uses the value of the form, and it doesn't have side effects, it's as if it wasn't there
(except maybe it makes your CPU spin I guess)
I see what you are saying, thanks...it is just very different than what I used to..but I am starting to get it
slightly off topic, i wonder if the compiler could detect and warn about ignored non-side-effecting forms
the problem is that with many forms you could redefine them
it would be very dumb to do so, but you are allowed to redefine clojure.core/= for example
for a warning it would still make sense though
I bet you could do it as an eastwood extension
it's very useful, catches the stupidest bugs without having to create unit tests or run the app, and tells you exactly where they are
hi, I'm wondering what's the difference between doing an anonymous function with fn and with #, besides just how you refer to the arguments
it seems like there is implicit "do" and other gotchas that make them different
is one implemented or exanpds to the other?
They in fact both expand to the same thing
nice, thank you very much
@brnbraga95 You can delete those two if
s -- as @noisesmith said, they don't do anything.
When Clojure evaluates a function, it evaluates each form in the body, but only returns the last form's value. In your case, the (if (= x 0) 0)
is evaluated but then ignored. Then the (if (= x 1) 1)
is evaluated and ignored. Then the loop
is evaluated, and it's result value is returned.
(you'll also want to get used to idiomatic Clojure indentation -- which means not putting )
on its own line -- and using kebab-case
instead of camelCase
)
Here's a version of your function, with the unused binding removed from the loop
, the unneeded if
s removed, and more idiomatic naming and indentation:
(defn fib-iterative
[x]
(loop [i 2, fib 1, x1 1]
(if (< i x)
(recur (+ i 1) (+ x1 fib) fib)
fib)))
(fib-iterative 10)
What is the difference between planck and lumo?
Planck sits on top of JavaScriptCore and has imitations of Clojure functionality found in
and clojure.java.shell
.
Lumo is running Node / V8 with all of the benefits you get with Node, and additionally can be used beyond just as a REPL / script runner, to compile ClojureScript files all the way through Closure.
They are both built using self-hosted ClojureScript, so launch instantly, and share lots of code between them for this purpose.
And just so you know, that was the creator of planck explaining the difference. This is a wonderful slack
Sure is, thank you!!
Really want to get into clojurescript
thanks @radomski
what I'm referring to is this
((fn [x] (str "hello " x)) "world")
returns "hello world"
but (#("Hello " %) "world")
gives me TypeError: "Hello ".call is not a function
also, what's the best way to use rand-nth on a map?
I guess I would want it to give me a map of just one key-value pair
@derpocious That anonymous function literal needs a str
in operator position, right, as in
(#(str "Hello " %) "world")
@derpocious I'm curious what the best way to do the random singleton map problem is
(let [m {:a 1 :b 2 :c 3}]
(rand-nth (seq m)))
succinctly gives you a random map entry, but
(let [m {:a 1 :b 2 :c 3}]
(find m (rand-nth (keys m))))
might be more efficient. In either case, you'd have to convert the map entry into a singleton map.true! thanks @mfikes!
how about this one though
(#((println "Hey")
(str "Hello " %)) world)
;; #error {:message "ERROR", :data {:tag :cljs/analysis-error}, :cause #object[TypeError TypeError: Cannot read property 'call' of null]}
((fn [x] (println "Hey ")
(str "hello " x)) "world")
;; Hey
;; hello world
@derpocious fn has an implicit do, #() does not
is the shorthand actually a macro? Or is fn a macro? What does it expand to?
user=> (macroexpand-1 '(fn [x] (println "Hi!") (inc x)))
(fn* ([x] (println "Hi!") (inc x)))
in Clojure, at least, and fn*
is a special form. See https://clojure.org/reference/special_forms#fn"The exprs are enclosed in an implicit do."
Anything that starts with a #
is handled by the reader,
user=> (read-string "#(str %)")
(fn* [p1__13#] (str p1__13#))
Has anyone manage to get Lacinia
graphql implementation to work with luminus?
Including getting the Docs
explorer of GraphiQL to work with the query root and schema.
A simple question, but i feel like it has large implications. Does it make sense to create getters? (get-x [m] (get m :x)
or just use the function directly and expose the implementation details? The first feels more resilient to change, for example, you change m from a hashmap to a atom containing a hashmap.
My inclination is to not create getters like this. Most of the time you will be dealing with actual maps or map-ish things like records. And if you have a atom you should probably not be passing the atom around like that. With atoms you want to pull the value out early and write most of your code to deal with the value, not the atom.
The getter would create an abstraction over the data so that change from a hashamp to atom would be shielded from the rest of the code. This is just an easy example i can think of. But yea, I agree, you should be using a hashmap for your data, so its hard to see how its helping that much…
So this is certainly a matter of degrees and probabilities. So think of my answer as an estimate of the probabilities: these kind of wrappers don't help very often so my default is not to write them. And I rarely have instances where I need to add the wrappers later.
That makes sense, I don’t foresee a large cost to making that change either. I too, don’t do it in practice, i was just trying to reason if i should have a different default mode.
However, it also implies that you should create a lot of encapsulation functions that are more or less wrappers around clojure core functions.
Hi guys. I’m using clj-http. I’m trying to get a CSV file. When I go to the page in a browser, the CSV file downloads do to the
"Content-Disposition" "attachment; filename=report.csv"
header. However when I make the same request using clj-http, the headers are correct and the body is ALWAYS emptyany ideas?
@mdrago1026 I'm a bit off context but are you sending in the correct :as
params to clj-http? take a look at the following example:
https://gist.github.com/philippkueng/11377226
@mdrago1026 maybe a more elegant (and less prone to out of memory errors) way would be something like:
(
(:body (client/get "" {:as :stream}))
( "report.csv"))
You know, I've been using [Common] Lisp for over a decade, and learning Clojure this week makes me just say "wow". This is going to completely change myself as a programmer.
Why can’t i recur from within a try/catch block? ex: i want to exponentially backoff and have specific error handling
(async/go-loop [last-delay 0]
(try
(do-things)
(when @active
(recur)))
(catch Exception e
(let [delay (if (pos? last-delay) (* 2 last-delay) 5)]
(log/error (str " Exception: " (.getMessage e)))
(async/<! (async/timeout (* 1000 delay)))
(when @active
(recur delay)))))))
@ben.borders take a look at this https://coderwall.com/p/6qu8vw/recur-from-catch
@ben.borders ClojureScript currently accidentally allows this, and this JIRA ticket illustrates the nonsensical behavior that can be produced given that you can have a finally
block with side effects: https://dev.clojure.org/jira/browse/CLJS-2476
I'm writing an api wrapper library and I'm wondering the best way to get user secrets to authenticate. I have the authentication part currently working by me setting the secrets in a .env file that is ignored in source control, and I load them into a config map and the auth functions use the config map. That's probably not ideal for a library that other people would use. I come from a more OOP background so I'm trying to rewire my thinking, and I know in that space one might create a client object with methods. The constructor of the client would take in the secrets. Then all methods on the client would have them as object state. What's a good way to achieve something similar in Clojure? Supply an atom for secrets in the namespace that the user can set, and the functions that require auth use that atom? I'm probably thinking about it poorly.
my approach would be to make a protocol defining the API, then a record which implements that protocol and has internal attributes to store whatever auth info you need
@brandon.ringe if you supply the atom, your library is now a singleton and they can't use two sets of credentials in one codebase
if they supply the atom (or better yet, provide credentials and then you return an object they can use - even if that object is just a function), then it's properly reusable
for example, see the protocols here https://github.com/amperity/vault-clj/blob/develop/src/vault/core.clj#L7 vs the implementation here https://github.com/amperity/vault-clj/blob/develop/src/vault/client/http.clj#L258-L260
@brandon.ringe if there's an advantage to disconnecting data from functions, do so (it's idiomatic in clojure), but that doesn't mean you need to disconnect data from code in all cases. If the function doesn't work without auth, why not a first class function that takes auth and returns a usable function? if it's better represented as multiple functions, then maybe it makes sense to make a record implementing some protocols
(which is pretty much what @greg316 described while I was busy typing heh)
IMHO it's good to go with a default of "separate data and functions" because traditional OO overemphasizes tying those together (similarly avoid defining new data types and interfaces because OO as it's taught today overemphasizes these things), but we still have the tools for interface abstractions and defining types and methods if it actually fits the problem
When you say separate data and functions, would that be the case of creating a http-client record that takes in the auth params and implements a protocol with the functions that use those auth params, or is that not separate? Sorry a little confused
another upside of splitting out the protocol definition from the client code is you can easily sub in mocks or other implementations: https://github.com/amperity/vault-clj/blob/develop/src/vault/client/mock.clj
@brandon.ringe I think you’ve got it - defining the protocol makes a set of functions for the consumers who want to use that API, but don’t necessarily care about the mechanics of how those requests are serviced “under the hood”. Whereas the authentication data is state which would be part of the client record you implement the protocol on.
so write your business logic against the protocol and you can test it in isolation by giving it a mock protocol implementation, then in production you can construct a ‘real’ client with the required auth values and pass that into your business logic functions
@brandon.ringe in general what I mean by separating data and functions is eg. the way hash-maps and vectors work. We have N reusable container types, and N functions that all know how to use multiple collection types.
a record implementing a protocol is tying data to functions - because the protocol methods are each functions that accesses the data you put in the record
(and can only be called via an instance implementing their protocol or interface)
@noisesmith I see now. But in cases where secrets are required this is a scenario in which that is ideal? Or do some people prefer to never use records with protocols that access record state, and rather prefer to use functions that return functions with the needed data enclosed (closure)? But in a case where say, 20 functions need the same auth params, you wouldn't want to have 20 higher order functions and require the user to pass auth params to every function right? I don't know what other options there are (literally don't know not saying there aren't).
@brandon.ringe right - if the functions are useless without the data feel free to tie them, and a defrecord over a protocol is a good simple way to do that
just saying that it should still be avoided unless it fits your problem (and it usually won't)
too often I introduce someone to defrecord and they take that to mean "OK I do OO the way I learned in my java class now and use defrecord" - just trying to be clear that it shouldn't be your go-to - make things with plain data and plain functions first
conversely, if you find yourself writing a lot of related functions that all take some “context” map, that’s a sign you should maybe make a protocol/record instead
like (defn foo [ctx a b] ...)
, (defn bar [ctx a] ...)
, (defn baz [ctx c d e] ...)
etc
How do you guys solve the SSR with reframe now a days? Is delivering an static page through Hiccup while ReFrame initialize on the client?
@noisesmith @greg316 Makes sense. Thanks for the help.