This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-12-22
Channels
- # adventofcode (35)
- # beginners (137)
- # braveandtrue (1)
- # calva (33)
- # cider (40)
- # cljsrn (4)
- # clojure (10)
- # clojure-spec (26)
- # clojure-uk (29)
- # clojurescript (18)
- # core-async (6)
- # cursive (1)
- # emacs (2)
- # figwheel-main (17)
- # fulcro (28)
- # jobs-discuss (4)
- # leiningen (1)
- # lumo (19)
- # off-topic (2)
- # om-next (1)
- # reitit (2)
- # rum (8)
- # spacemacs (19)
- # tools-deps (9)
- # yada (3)
Hello lovers of metadata.
(meta ^:extra even?)
returns nil
. Metadata reader macro ^ is not supposed to work on symbols, as per https://clojure.org/reference/reader#_metadata. On the other hand, it throws a syntax error for non-IMetas (such as ^:extra 1
). Hence, when it doesn't throw, one could expect it to work. But why doesn't it then throw a syntax error, instead of being silent?
user=> ^:extra even?
#object[clojure.core$even_QMARK_ 0x41d7b27f "clojure.core$even_QMARK_@41d7b27f"]
user=> (meta (with-meta even? {:extra true}))
{:extra true}
user=> (meta ^:extra even?)
nil
Yes. But since both following ways apply the metadata to {}
literal
(meta (with-meta {} {:extra true})) ;=> {:extra true}
(meta ^:extra {}) ;=> {:extra true}
wouldn't you expect the same when applying to a symbol?
(meta (with-meta even? {:extra true})) ;=>{:extra true}
(meta ^:extra even?) ;=> nil!
I don't mind that ^:extra even?
doesn't apply meta (as per documentation it's not supposed to), but it would be helpful it if reported an error.
There are a lot of things in Clojure that have undefined behavior -- and coming from a C/C++ background I think that's fine.
When something isn't specified, the most performant option is a reasonable choice.
When the doc/spec says something "doesn't apply", that doesn't mean it should produce an error or that it should behave in a particular way.
I only care if the docs say "X should work" and it doesn't 🙂
Thank you. I can see this perspective gives more peace of mind.
clojure.set
is a great example of this -- lots of its functions behave very weirdly if they are not given sets as arguments, but their docstrings only define their behavior for set inputs.
The Eastwood linter gives warnings for some things that Clojure does not give an error about, that might be mistakes in your code, but not necessarily everything you might wish it would warn about: https://github.com/jonase/eastwood
Hi all, I have simple function that adds the first two numbers in a vector : `(defn adding-first-two-of-v [v] (if (< 1 (count v)) (+ (nth v 0) (nth v 1)) (nth v 0) ) ) ` what would be the correct way of adding looping over a given vector?
hi @ali.ebadian, your function can be implemented in a more simple way like this: (defn add-first-two [v] (apply + (take 2 v)))
@josip.gracin thanks, looks like i got a long way to go
In general, how do ppl go about spelling checking there clojure programs?
strings, symbols, keywords, etc..
Do you mean, looking for errors that will cause the program to misbehave? Or do you mean, are these names in this English/Dutch/French/etc. dictionary?
Both? This is probably a editor specific thing. On spacemacs with the lintet joker, the mis spelled symbols aren't highlighted. I can use ispell buffer to check for dict words, but then it seems like I would need to add a lot (fn, nil, etc...)
I think something that accepted none project code as valid, but raised warnings about code I added wild be good enough
I suppose I could run a spell checker on the code diff
i'm curious about deployment of clojure programs once I (if ever) finish a real project. So something like lein uberjar
creates a .jar
file right? And then what? I give that .jar file to a user and they can just run the program? I tried to move the snapshot.jar file out of the project and practice just randomly opening it and couldn't figure that out.
lein uberjar
produces two .jar
files, one with and one without the runtime dependencies of your project. Both are executed via java -jar
, but you must provide the proper classpath to the latter.
@peter.kehl @seancorfield re the metadata questions above -- what you're observing is a bit more nuanced than that, the disconnect you see wrt with-meta
^
and collections/functions is due to when that metadata is applied
when you do ^:foo even?
or ^:foo [1]
, {:foo true}
is attached at read time to the object and available at compile time
but for clojure collections and symbols, compile-time metadata is propagated at runtime
also, reader metadata is supported on symbols, but the syntax would be (quote ^:foo x)
so '^:foo x
not ^:foo 'x
which would be ^:foo (quote x)
, thus applying the metadata on the quote
expression rather than on the quoted symbol
hey I have a question... Currently I use {:input 'my-input-function} and then I use ((resolove (:input myfunctionmap)) to invoke that function - but there should be more idiomatic and more beautiful way of doing so What I want is to be able to change some keys referencing input and output functions for my program, and use them when need either input or output
Is there a specific reason why you are putting the symbol in the map, instead of the function itself? Otherwise, putting the function instead of the symbol would remove the need for invoking resolve
.
Also, you can take a look on dynamic vars and binding
, which would remove the necessity for the map.
Since I am also a beginner, I am interested in seeing some other technique for doing this.
well I have defined like default input and output functions somewhere... which are stupid read-line and println respectively
but I want my application eventually to work with web input and render to html as output
so I want all the other program be totally unaware where it is geting it's input from and how output is being performed... so I was thinking to put those references of functions into map which is in general whole data of whole program, and when passing around, it is used by program to read and write stuff
I see. I will come up with a quick binding
example, I believe it will suit your needs
with my guts I feel I am not doing it idomatically, but how else one can reference functions?
(def ^:dynamic *my-input* 3)
(defn print-my-input
[]
(println *my-input*))
(print-my-input)
(binding [*my-input* 200]
(print-my-input))
Instead of the number, you can use a function
what I want is to have data structure, which also contains (by keys) function which can do something, like input and output itself
and then program which uses the data structure, just looks up the input/output function by key inside the data strucutre, and uses it to get inptuts and outputs
You can define the dynamic var as a function. The number was just an example
probably it's my OOP kicking in, but I want to have function of the data strucuture to live inside that data structure - probably bad idea
but it simplifies my program, so that all of my top level functions all take only one parameter - my data structure
and then separate functions just pick parts of the data strucutre, But occasionally input is needed and output is needed, so it would be nice to reference the same data structure for the "currently configured" input/output functions
of course, when the data structure is initialized at the beginning of the program, those input/output functions are defined assigned...
If you want to keep the function in the map, you can put the function itself as the value of the association.
Your example was:
{:input 'my-input-function}
and ((resolve (:input myfunctionmap))
You can remove the quote and the resolve
:
{:input my-input-function}
and ((:input map))
If you want to change the function in the map, just use (assoc map :input new-func)
so I just made expedriment and it works, looks like this is what I want (def myoutput println) (def struct {:output myoutput}) (let [output-function (:output struct)] (output-function "Whatever"))
now I found another problem (in future) With normal console, I know when I need input, and I explicitly ask, and block program waiting for tha tinput But for web... it's not that possible... for that I have to somehow wait for input differently, as user will be invoking some REST API as "input" to my program, and where in the first case app is initiator of input, in other case it is remote user kicking my server through API giving that input at some arbitrary time
That is because the API is more "reactive" than "imperative". Your program will react to requests. You can build the console version of the program in the same way as the web version is. The thing both have in common is the way the input is dealt with, so you can separate this logic in a pure function. The difference is the way the input is taken, so you will have to separate the read/write logic. For the API case, you will get the request, pass it to the logic function, grab the return and write it back to the client. For the console case, you will prompt the user for input, pass the input to the function, grab the result and output to console.
Things will be easier if you separate the logic from the input/output handling
Instead of putting the in/out funcs in the map, you can completely remove them and pass only the data to the function. The function will return the result and then you deal with giving it back to the client. Each interface (API/console) will implement it's own ways of handling IO
yea, I guess I will do this, coz now I see that input/output got inside function which should not do anything of input/output just react on it... and don't care where it came from
yes, exactly
this is why people will often talk about building functional systems as an onion. The core will have only pure functions, and the side-effecting functions will be pushed toward the outside
it is way easier to unit test systems like this
yes sure... and that is essential for me too, as I have not much knowledge at all about clojurescript and ring and compojure etc. so until I will get to web, i want to test my program without the web at all... pure console input/output and then I will start learning next things - clojure for web
but as my program in general is "game" (board game) I have to read turns from users, where each user can have several actions on each of their turn So it is somewhat thinking need to be done Like infinite loop of inputs/actions/outputs -> inputs/actions/outputs -> and so until end is reached
That is normal, I am also still learning. It was very hard, especially in the beginning, to wrap my head around the functional style, coming from an objected oriented perspective. It is just a matter of practicing a lot, reading other people's code (libraries, applications, etc.)
and whole game state is kept in one huge map, but then I have to "chop" each step into some "snapshot" of the game, so I can use reactive approach, and always know on what stage where I am
I see. You may want to take a look on Clojure's reference types, to maintain the state of the game as time progresses. That would be useful for both web and console version
Especially in the web version... that would allow you to maintain the the state of the game in memory, and update it as requests come from the web
(in a thread safe manner)
You can define the valid transformations to the game state as functions (as you may already be doing). When a request comes, you decide which operation is to be done, apply it to the current state of the game and get the resulting state as a return from the function. From there, you can write to the reference type and return something to the client
yes, this second part I figured, now I need to remake some stuff, to make the input part correct, and yes, transformations are the one good approach
cool... make sure to come back to the channel and ask if you have any modeling questions. There are pretty smart people in here that can help you
@bronsa Ah... thank you!
@bronsa Thank you.
I see now: (meta (quote ^:flag even?)) ;=> {:flag true}
Does it mean that when using ^
with a symbol, it attaches the meta to the symbol before the symbol gets evaluated? If so, does it mean that literals get evaluated before symbols? But wouldn't you naturally expect it to attach the meta after the symbol gets evaluated?
which follows from what I described above: for clojure objects (collections, symbols), the metadata is propagated from read-time to runtime (and thus gets also evaluated)
for symbols it can appear a bit more confusing since you can't produce a runtime symbol to which you can attach metadata using the reader syntax without quoting it, so even if technically possible it's practically just restricted to collections
@bronsa Wow. Everytime I get more comfortable with Clojure, there's more to study. Simple language that allows ideas to be big. Thank you.
Having problems with Java interop. Does anybody know why this method is not resolved? Trying to compute successor of the TreeMap-node
(java.util.TreeMap.Entry/successor ...)
@denisgrebennicov Since when does java.util.TreeMap.Entry
exist? I can only see java.util.Map.Entry
. https://docs.oracle.com/javase/9/docs/api/java/util/TreeMap.html =>> https://docs.oracle.com/javase/9/docs/api/java/util/Map.Entry.html
it’s sad that clojure sorted-map
aka PersistentTreeMap has no successor func.
Feels like I have to do some mambo-jambo to make it work, or write in Java
😢
actually ceilingKey
would work just find in my case, since this is what I want, but I want this to be done on PersistentTreeMap
- sorry for kinda wrong question though
Is there a way to dynamically apply a map to a keyword-arg function? Like
(defn f [& {:keys [x y]}] (+ x y))
(apply f {:x 1 :y 3})
@UCQL6E7PY I’m having trouble piecing together how concat would replace flatten in this case?
(apply f {:a 1 :b 2})
;; => ([:a 1] [:b 2])
;; we want the return to be (:a 1 :b 2) for the {:keys [...]} syntax to work.
(apply f (flatten (vec {:a 1 :b 2})))
;; => (:a 1 :b 2)
;; works when the input is not a collection
;; but fails in this case:
(apply f (flatten (vec {:a [1 2] :b [[[3]]]})))
;; => (:a 1 2 :b 3)
;; using concat ensures only the top level is joined:
(apply f (apply concat (vec {:a [1 2] :b [[[3]]]})))
;; => (:a [1 2] :b [[[3]]])
(apply f (apply concat {:x 1 :y 2)))
that works. In so far I like (apply f (mapcat vec {:x 1 :y 2})))
no problem! mapcat vec
works, but I'd expect it'd be a little less performant due to the calls to vec
. Ultimately probably not a big deal
@U8WFYMFRU Is core.typed on your radar? If so, you'll find it (currently) impossible to type-check such calls. See https://circleci.com/blog/why-were-no-longer-using-core-typed/ > apply-map
.
There are lots of things core.typed
couldn't do back then...
@peter.kehl Good idea to keep that in mind but I don’t think it’s on the horizon for this project.
@denisgrebennicov Did you try clojure.core/subseq
? Its doc: ([sc test key] [sc start-test start-key end-test end-key])
sc
must be a sorted collection, test(s) one of <, <=, > or >=. Returns a seq of those entries with keys ek for which (test (.. sc comparator (compare ek key)) 0) is true.
according to https://github.com/clojure/clojure/blob/clojure-1.9.0/src/clj/clojure/core.clj#L5049
it just applies seq
and takes the items while the test is true
@denisgrebennicov apropos
and https://clojure.org/api/cheatsheet are your friends.
You can also reverse a sorted collection efficiently with rseq
.
I'm banging my head against the wall here.. What's the correct way to clear a session with luminus/immutant? Right now I'm doing this:
Eh, figured it out - instead of removing the session from the response map, I had to set it to nil
Hey guys I am reading clojure reference doc about The Reader
and the first line start saying Clojure is a homoiconic language, which is a fancy term describing the fact that Clojure programs are represented by Clojure data structures.
@quieterkali It's core to why macros work the way they do. Consider (defn foo [a] (println "Hi! a))
... that's a list with four elements...
(list 'defn 'foo '[a] '(println "Hi!" 'a))
and the third element is a vector with one element
(list 'defn 'foo (vector 'a) (list 'println "Hi!" 'a))
-- that would compute, at run time, the data structure that is also a function definition