This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-11-20
Channels
- # aleph (12)
- # announcements (7)
- # aws (6)
- # babashka (36)
- # beginners (161)
- # boot (1)
- # calva (6)
- # cider (21)
- # clj-kondo (13)
- # cljs-dev (28)
- # cljsrn (1)
- # clojars (3)
- # clojure (13)
- # clojure-colombia (1)
- # clojure-europe (10)
- # clojure-spec (12)
- # clojure-uk (47)
- # clojuredesign-podcast (2)
- # clojurescript (67)
- # datascript (8)
- # datomic (21)
- # duct (3)
- # emacs (6)
- # events (1)
- # fulcro (6)
- # graalvm (98)
- # jobs (1)
- # kaocha (18)
- # luminus (1)
- # malli (7)
- # off-topic (56)
- # pathom (5)
- # re-frame (18)
- # reagent (3)
- # reitit (9)
- # remote-jobs (3)
- # rewrite-clj (10)
- # ring (1)
- # shadow-cljs (155)
- # spacemacs (2)
- # sql (5)
- # tools-deps (27)
- # vim (86)
- # xtdb (2)
So if I understand right, having all the source files in src/project-name/ prefixes their ns's (e.g. project-name.foo) and prevents grief if I end up bringing in a lib also named foo? And it sounds like you can nest additional subfolders to organize your stuff, and that will be reflected in the ns's as well? Neat.
although it's more that the namespace must reflect the folder layout rather than the namespace "will" reflect the folder layout. in your (ns project-name.foo
declaration you have to specify the full and correct namespace as dictated by the folder nesting
@lockdown- thanks
Most floating point numbers (Java type float and double, based on IEEE 754 standard) are approximations. This section of the Clojure equality guide article might have some useful info: https://clojure.org/guides/equality#_floating_point_numbers_are_usually_approximations
I'm connecting to a Socket with clojure and I'd like to read messages from the socket, then for each message I receive I'd like to call a handler function. I'd like the handler to happen in another thread, but ultimately when it returns a value, I'd like to queue that up to send as a response over the socket. Does anyone have a recommendation on how I should approach this? I've written the code to connect to the socket, send message, and receive messages so far. I'm not sure how to approach the rest.
Should I setup separate threads for reading / writing to the socket, so that one can block on reading, the other can just wait for messages, then send them one at a time?
A common pattern is to have one thread that accepts incoming messages then hands them off to a pool of threads to respond
Looking at core.async now. Just unsure of what approach / library that would be appropriate here.
In Java, I would probably create a fixed thread pool executor service and could handle message processing that way.
I’m not sure core.async helps you a lot here, I would just do that
Would this be the relevant reading material - https://clojure.org/about/concurrent_programming ?
you can look at https://github.com/clojure/clojure/blob/master/src/clj/clojure/core/server.clj#L115-L117 to get an idea of how clojure's built-in socket server works
its not quite what you're looking for but perhaps it can serve as a jumping off point
Thanks, that's helpful! I'm trying to learn the "clojure" way of doing things and every time I fall back to Java I'm worried I'll implement my solution in a familiar way that prevents me from seeing the benefits of functional programming.
I'm basically porting a working c# app to clojure in order to learn Clojure and hopefully provide an example to others I work with on the benefits of Clojure. (The REPL is the best part so far)
if you internalize immutable values and write java flavored clojure i don't think you're in a bad spot to create lots of functional things. as you read code and run into tough spots from writing java flavored clojure you'll discover benefits of different ways. but don't let the perfect be the enemy of the good. and always ask questions here 🙂
Thanks for the encouragement. So far the "socket" is the only part of the application that isn't "purely functional" so I already see other benefits.
(`defmacro ^:private thread
[^String name daemon & body]
`(doto (Thread. (fn [] ~@body) ~name)
(.setDaemon ~daemon)
(.start)))
So I was looking at the code and I saw (thread ) but I didn't know what that was, so then I saw the definition of a thread macro. Should I just use this as-is and not ask questions 🙂 or do I need to understand a bit about what this is really doing?
It looks like it's creating a thread, setting the daemon flag, and executing what's the in body within the thread's run method and starting it up. Is that a valid take? I haven't written or read much on Macros so far.yeah. the real benefit to this is the obvious, it ensures that set-daemon is set. and it also enables a bit of sugar in that it takes a form and wraps that in a function rather than requiring the caller to do so. So this doesn't need to be a macro but makes the usage a bit nicer
if you see how its used, one of its arguments is the form (accept-connections conn ...)
. If this wasn't in a thunk then it would be evaluated on the calling thread rather than delayed and invoked on the newly created thread
Is there an easy way to make a function synchronized so that only one thread can enter at a time?
;; lock protects servers
(defonce ^:private lock (ReentrantLock.))
(defonce ^:private servers {})
(defmacro ^:private with-lock
[lock-expr & body]
`(let [lockee# ~(with-meta lock-expr {:tag 'java.util.concurrent.locks.ReentrantLock})]
(.lock lockee#)
(try
~@body
(finally
(.unlock lockee#)))))
I think I found the answer in the code.this looks like an attempt to do clojure.core/locking
from scratch
now I see this is in clojure.core.server, I wonder why one would use this instead of locking
(or visa-versa...)
Do I have to know Java before learning Clojure? I want to avoid Java if possible.
For additional context, I’m comfortable with NodeJS/Typescript, Python, PHP, etc. I did some Java back in the day but didn’t enjoy it.
Clojure uses a lot of underlying Java DS and libs, i reckon you might want to look into common Java DS?
there might be time when you want to make use of Java as well like the code block above with ReentrantLock
@noelmartin you can get a long way with Clojure without knowing Java. About the only skill you'll need is reading stack traces IMO
Nice. I’m backend-oriented so I’d like to start learning Clojure by writing up some backend APIs. Any suggestions for Clojure equivalent of batteries-included web frameworks (e.g. Django, Rails, etc.) and microframeworks (e.g. Flask, Slim, Express, etc.)?
@noelmartin I'd suggest checking out some of the frameworks referenced in "Web Development with Clojure" - https://pragprog.com/book/dswdcloj3/web-development-with-clojure-third-edition I think Luminus is the framework, but it uses several libraries.
Perfect. I prefer learning from books so this is great!
Any way of turning warn-on-reflection only for own source files, and not for dependencies? Or is this a bad idea?
@noelmartin https://www.youtube.com/watch?v=0EX3UIl-Sd8 This was a great talk that goes in depth and clarifies a fairly standard and idiomatic way of constructing a web application, and is also filled with solid suggestions for further study. With the plethora of choices in Clojure web development, this was really grounding and helped me see not just what choices exist, but why they exist and how each is useful.
Do you append !
for impure functions that read state in either atoms or external databases or should it be only for functions that modify state?
My 2c: it's a sign for "caution, side effect", so for reading atoms/database I think it's not required.
Even clojure.core is not consistent here.
- persistent!
has bang because it is destructive on the transient argument.
- alter
and alter-var-root
don't need it because they are within the epochal time model.
- But swap!
despite being in the epochal time model has a !
.
- run!
has a bang because it's intended for side effects
- print
and related don't even though they're effectful.
I can go on but, you get the point. I'll leave you with a snippet if you wanna look at all the stuff in clojure.core with a !
:
(->> (ns-publics 'clojure.core)
keys
(map str)
(filter #(re-find #"!" %)))
In general side effect is anything that causing unpredicted behaviour. Reading from atom could return different results depending on the state of atom.
I'm leaning towards not putting a bang for database reading functions. Being too strict about putting a bang on side effect functions isn't helpful either, as even print
has unpredicted behavior
The modern usage of the word behaviour is a bit vacuous. One precise definition of "pure function" is "referentially transparent", because a fn that prints something always might return the same output given the same input. But still won't be a pure function as per this definition.
Should we name all fns that aren't known to be referentially transparent with a !
? Maybe. Maybe not.
There’s a bit of a distinction between “causes side-effect” and “is impure.” You could have a function that returns the same result predictably based on the same input, and causes all kinds of havoc on the side. You could have another function that returns unpredictable results (`rand-int`, for example), but doesn’t mutate anything in the environment. Reading the DB is impure, but presumably doesn’t side-effect. I tend to use bangs for mutations.
Scheme has traditionally used !
to denote destructive mutations, and specifically not I/O
Hello, clojurians, I need some help from gurus 😉 I have a question about state management in Clojure. As everybody does, to make learning fun I'm trying to build a small game. It's a card game and it has a lot of rules, units, spells, and all this stuff. And the biggest problem that I'm struggling with now is how to organize game state and make it simple to debug & maintain. I spent much time trying to google how people organize the state in web apps and libraries, but it still hard for me. The most confusing part is that I can't find any alternative to "map in a single atom" approach. So, the question is -- how to organize program state (runtime state) in Clojure without tears and is there any way to manage state in isolation
A guru I am not, but I'm also writing a game to help me learn and I decided to go for a map in an atom. The map is deeply nested and I have getters and setters that abstract away the really confusing logistics of actually using data that is stored like that. My game, if you wanna see the work of a new clojurian: https://github.com/doby162/witchazzan-server
Yeah, I ended up with smth similar, but all this "narrow" functions and "update-in"s are quite disappointing. I just stopped and decided to look for any alternative, but only thing that comes to my mind is FRP based on atoms & watchers
For what it's worth, before I went for the nested map I just had global vars that were vectors of atoms, each atom being the state of a single object. The linters hated it because I constantly added and removed things from global lists by re-defing them, but it was way more intuitive and didn't actually cause any problems yet. I think the problem would be lack of thread safety.
One of the option is to use Component
but I think it too heavy for small game https://github.com/stuartsierra/component
I'm more eager to learn atom
based approaches
mount-lite can be an option too https://github.com/aroemers/mount-lite
If you’re happy to try out CLJS, you could have a go at it in Reagent with React backing your rendering.
It has a more opinionated answer to state with regards to the view = function(data)
relationship.
You do end up dealing with atoms, however, and the general consensus is that a single global atom is the way to go, with small atoms internal to a component desirable only when there truly is no coordination with the surrounding environment.
Well, thank you for the answer. I plan to create main game logic on backend and then start develop client with cljs
https://github.com/weavejester/integrant another alternative to component or mount-lite
Mine is multi threaded, it's online multiplayer and each player gets a worker thread, plus the main game logic is offloaded to a thread so that the repl can be used to manually inspect game data
If its multi-threaded. You can define your game state in refs. And when you need to modify more than one ref atomically you do it in a transactions.
If your game is single threaded, you can use atom instead of refs, they're a bit faster since they don't require transactional machinery for concurrent access
For complex games, an entity component system could be used: http://entity-systems.wikidot.com/
But basically that way you can just manage state as you would in any other programming language
FWIW I am handling my game state with DataScript and enjoying it a lot. Also using something of an entity-component system. Not sure if its for absolute beginners though.
And may not be usable for real-time games... mine is something of a slow-paced MUD
I don't have a lot of experience in game state management in general. But Clojure shouldn't really require you to change the way it's done.
Yea I was trying to write something up that basically gets to what didibus said; you can break it up the same in Clojure, either by splitting up the top level pieces of your program in your top level function, or keeping them together in one data structure
Thanks for the options! I'm only a beginner to clojure so I'm not afraid to try more involved solutions
and even when you do package it together, you can still write functions that deal with one layer each, rather than writing all the functions to start with the gameobject and 'reach in' and dig around for the things they need and to carefully place their changes in that same spot without disturbing anything, like some spy movie where Frankie Munez is rappelling from the ceiling and carefully replacing the super expensive diamond with some decoy
Of course, when you write your changes directly just for the things they affect (meaning, you don't write something like
(defn attack-player [gameobject]
(update-in gameobject [:players :main :health] - 12))
but instead
(defn attack-player [player]
(update player :health - 12))
Yes, you will still need something responsible for sending those changes to the appropriate spot in your overall dataAnd usually I suppose I'd do that is in layers like (this is probably gonna take a bit to type up):
Maybe to make things more clear. If you had in an OOP language:
class Player {
x-location = 0;
y-location = 0;
move-by(x, y) {
this.x-location += x;
this.y-location += y;
}
}
class Game {
player = new Player();
start() {
player.move(10, 30);
}
}
Then in Clojure you can just do:
(ns game)
(def player (atom {:x-location 0 :y-location 0}))
(defn move-player-by
[player x y]
{:x-location (+ (:x-location player) x)
:y-location (+ (:y-location player) y)})
(defn start
[]
(reset! player (move-player-by @player 10 30)))
This is sort of hard to come up with on the spot without a real example to pull from but when your top level pieces are all in one map, you might have
(def gamestate {:map { :mobs {:main .. :enemies ..}}})
(defn step-gamestate [gamestate]
(step-map gamestate))
;; How does the map change in one step of the game?
(defn step-map [map]
(-> map
step-physics
step-battle))
;;I'm not going to destructure here to hopefully be as clear as possible
(defn step-physics [map]
(let [ mobs (:mobs map)
enemies (:enemies map)]
.. figure out where everyone gets to move to
.. return new map))
(defn step-battle [map]
.. get all pairs of battlers,
.. battle all pairs of battlers
.. marge results back into map)
(defn battle [attacker defender]
.. return attacker and defender after battle)
Where each layer is just responsible for computing changes to its own layer, and each outer layer sends its change functions to its own constituents, which themselves have to send change functions to their constituents.and one thing about this is it stays pure for as long as possible (in a real example of course above this there's going to be other things happening, like input being read and passed into step-gamestate
), holding off on becoming imperative until its finally necessary, which would happen in the main loop where each step of the gamestate is updating an atom, and where the gamestate is being interpreted to produce things like screen updates and sound effects
why would we want to avoid a def? Putting the gamestate in the global state makes it easy as pie to inspect with the repl
That's fair. I was just trying to point out an atom is never really neccessary. The whole thing can be pure beyond IO
if you're referring to my def didibus, if you have something like that it would represent the starting point for the gamestate, but in this case I actually wrote it just to show a rough example structure of the gamestate
and then yes, you'll have an actual atom holding the living state, whether it be in the main function or outside of it
It's fine to have an atom for it if you want to inspect it and all. But if nothing outside the main loop uses it, it doesn't need an atom even. It's just the next iteration of the game state
In fact, I wasn't even thinking about it, but as I do I can say none of my recent projects have any atoms (currently at least), just main functions that recur
Ya, I think what confuses most people is that they don't get that you don't need any state. Your functions don't manipulate global state anymore. Your examples are good in that regard. The reason your layers don't need to access the global state map and reach in and out is because you don't need mutation anymore. You take data in and return the modified version of it out. It starts from the top layer down, and once everything returns your game state is rebuilt and you now have the new game state. Put that in a recursive game loop and voila :p
At some point, you need side-effect where you take user input from IO and return the sound and graphics and all back to IO. But the actual state is just old-state to new-state based on user actions, and the current game state events.
Easier said then done. But the way @UBCSS6NGK showed with their code examples is a good starting point for sure.
Aha if you're telling me specifically why my examples don't need access to a global state map, I'm well aware, although I'm sure you're speaking in general, or a little of both! I used that example exactly to show that, not accidentally show it. I want to be clear about the atom thing; my surprise is not knowing that you don't need an atom, it was that I was not even thinking about that at all, or the fact that I even realized that I haven't used an atom myself in a while. But overall, the addition or removal of the atom is not the important part to me (another reason I wasn't thinking about it), the important part is expressing your turtles changes pure all the way down, and not giving that responsibility to the atom (sending the atom the step-game function does this, but if you start breaking down that function and you directly feed it to the atom, now you are making the atom responsible for composing changes with mutation that could have been pure, and now you've not made it pure all the way down). After that point, keeping the atom is not adding or removing anything, in the same way Theon was still around when he lost his name; your program does have state, in the sense that the final layer of your program is always finally imperative, finally brought to life, and at that point the atom just serves to give a name to it, one extra window for observation (and is a win there). You indeed don't define your changes in term of that state though, they just describe what should happen, without being tied to an implementation. With the example where even the top level function on gamestate is just recursive, you might say don't have to even ever explicitly mention the state elephant in the room. Eventually, a pure function must decay into an effectful imperative one to bring forth life, and so something will compose it with an imperative implementation -- whether its explicitly done or behind the scenes. Of course, there are certain higher level aspects I would like to think on (does keeping an atom mean the next person is more incentivized to add changes imperatively?) , so note I am not actually speaking for potentially complex higher level trade offs like that (a psychological trade off, for instance). This is really hard to word, so some of the things may not be exactly what I'm trying to express. @U0K064KQV
@UBCSS6NGK Sorry, I think things got confusing down the road. I agree with everything you said, and I think the examples you gave are good ones.
I was just pointing out in theory, the game loop could also just carry the top level state locally. That would be the FP way. It's okay in Clojure to put it in an atom if that makes debugging or other things easier.
I'm currently trying to read a line from an inputstream and call a function to handle that line. I need this in a loop until the line is nil. What's the best way to do this? It's like I need a let binding in a while condition or something.
(doseq [line lines] (f line))
should work for you. you can also use loop
if you want a bit more control over when to recur
@U11BV7MTK I tried (doseq) but it treated the first returned string as a sequence of characters. Any idea what I did wrong?
that's on a single line. so it returns a string and that's a sequence of characters
the source of which is probably a just a hair snazzier than the solution you are writing or were just about to write
I have a question that I feel like there is a simple answer to, but it's not clicking. I have a string arg in a function that I want to convert to edn with clojure.edn/read-string
. Sometimes the string arg will be a string representation of edn, and sometimes it will just be an actual string, like "hello world"
.
If it's just a normal string, I want to leave it as is, but if it's a string representing edn, I want to call clojure.edn/read-string
- because if I call that on a normal string like "hello world"
I just get hello
returned (a symbol I believe, because it was expecting edn).
So how can I make this work for both strings and edn-as-strings? Do I need to check if the string is edn-as-a-string? How would I do that?
this mimics when people try to handle a single element and a collection of elements in a single function
probably not important to you but fwiw that's narrowing your api so that it only accepts a subset of edn. if you have external consumers or whatever you might want to document that
@brandon.ringe One other thing to watch out for (clojure.edn/read-string "80")
will work fine, but (clojure.edn/read-string "08")
will throw a NumberFormatException.
It caused me all sorts of trouble with one of my early Clojure projects - I was reading in months and it worked totally fine for January - July, but once I hit August the whole thing stopped working properly 🙂
it's the same thing clojure does if you enter 08
at the repl
user=> 010
8
ya, numbers prefixed with 0 are octal and 0x are hex according to java, and so for clojure
user=> (Long/toString 683306015 36)
"batman"
clojure must be the first language that has a literal for base 7
010 is base 8 - or do you mean eg. 7r10 ?
yeah, I find it funny that you can have a strange base like 7 like that
or more relevant to the initial point:
user=> 10r08
8
no, I was referring to the comment you made about keywords on integers not being great
It's poor practice.
Even tho' Clojure "allows" stuff like :0
it should be avoided -- either use actual numbers as the keys in the map or use keywords based on symbol names.
what I'm doing is trying to generate Step 4 here for my apps: https://github.com/reagent-project/reagent-cookbook/tree/master/recipes/filter-table#step-4-create-a-reagent-atom-called-app-state
That has maps with :id
and other keys.
Or mapv
if you want a vector of maps rather than a sequence.
ooo... I just got rid of my ugly imperative style for loop I'd written earlier today!! thanks a lot guys
also, {0 "yello" 1 "yello2" 2 "yello3"}
is allowed
you don't get the convenience that the key implicitly calls get, but you can work around that by calling the map, or just using get