This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-08-15
Channels
- # architecture (5)
- # babashka (34)
- # beginners (72)
- # calva (42)
- # cherry (31)
- # cider (14)
- # clojure (27)
- # clojure-europe (11)
- # clojure-norway (17)
- # clojure-uk (1)
- # clojurescript (25)
- # community-development (13)
- # conjure (1)
- # core-async (11)
- # datascript (18)
- # datomic (11)
- # emacs (12)
- # fulcro (10)
- # integrant (5)
- # introduce-yourself (3)
- # jobs (8)
- # juxt (2)
- # malli (22)
- # off-topic (11)
- # pathom (18)
- # polylith (62)
- # rdf (18)
- # reagent (8)
- # releases (1)
- # shadow-cljs (35)
- # sql (3)
- # squint (141)
- # tools-deps (12)
- # vim (4)
- # xtdb (4)
How can I redirect (System/out) when I use println
print something to other place like file or UI output window
Or redirect clojure.tools.logging
's log/info
https://stackoverflow.com/questions/36636718/clojure-out-vs-system-out and https://stackoverflow.com/questions/4183408/redirect-stdout-to-a-string-in-java seem to have some good info on it (clojure and java in particular)
those may be a bit misleading. The Clojure print functions will print to clojure.core/out
so you can bind out to some other stream around the print functions
(binding [*out* *err*]
(println {:hi :there}))
will for example bind out to err during the print call (printing to stderr instead)if you want to bind to a file stream...
(require '[ :as jio])
(let [f (jio/file "log")]
(with-open [fos (jio/writer f)]
(binding [*out* fos]
(println {:hi :there}))))
and sometimes it's useful just to dump a string to file (see spit
), or to print to a string, then put it somewhere else (see pr-str
or print-str
).
can I bind out in global ? and than all call println will print to file?
if I want to print UI , should I define self MyPrintStream extends PrintStream and than overwrite print method to print string into the output window's textfield?
(binding [**out** myPrintStream]
bindings have per-thread values. there is a root value for the out var and you could alter it directly (with alter-var-root), but then any print from any thread would go to the rebound out and this can be a pretty frustrating way to work (since that includes repl outs etc). this is not typically done. it would be more common to make a function that rebound out just in the function scope to print to the desired location, or format the log message to a string, then .write directly to a log stream
for text fields, they typically want a string, not a stream, so you're better off printing to a string, then setting the text
in both cases, you may also want some kind of queue in front of printing so you're not blocked waiting to print
most clojure log libs have the ability to take care of all this for you
Thanks. Yes I want to redirect log output message to the UI, But I don't know how to do it There are no examples
That will probably depend on which logger and which ui
I used to the log4j and UI used swing JTextArea with seeaw. I define the callback function in core function like this :
(defn dosometing [log-fn]
.....
(log/info "lala")
(log-fn "lala")
)
and then In the UI side :
(dosometing (fn[e] (log-to-textarea))
This is my reslove solution. I want (log/info )
to the textarea not use the callback functionThe built-in implementation of Clojure maps uses a memory-efficient "array map" that takes linear time to do lookups, but only up to a small limited number of key/values pairs, I believe 8. For larger maps, it switches to using hash maps, where (seq my-map)
returns key/value pairs in the order of the hash value of the key, which is almost never the order that they were added originally.
There are other implementations of maps, not built into Clojure, but available in separate libraries, that preserve the order that keys were added to the map. ordered-map, for example, in its implementation, maintains a regular Clojure map for fast hash-based lookup, but separately keeps a vector that preserves the order that the keys were added to the map: https://github.com/clj-commons/ordered
However, note that if you use the ordered-map library, or nearly any other non-built-in library with a different map implementation, there are still many Clojure core functions that return maps with Clojure's default built-in implementation, and using any such function will thus return maps that have "forgotten" the original key insertion order.
Feel free to ask more about your particular use case for why you want the original sorted order of the key/value pairs, since then someone may have more specific advice on how to handle it.
@U0CMVHBL2 wrote: "using any such function will thus return maps that have "forgotten" the original key insertion order" Great point ^^^. Kinda like swimming upstream. 🏊 If the order is meaningful, perhaps it could or even should be made explicit as a new attribute. 🤷
Examples of Clojure core functions that return Clojure built-in maps, even if you pass into them as parameters a custom map type: select-keys
, update-keys
(sometimes update-vals
, depending upon whether the map you give it implements transients or not). This is NOT intended to be a complete list, just a quick check of a few Clojure core functions that return maps. If you see a base case of {}
in some implementation that is built up into a return value, that is a pretty good sign that it will return a Clojure built-in map, rather than a custom map type you provide as a parameter.
If you see a return value that is created from the parameter(s) via only operations such as assoc
, that is a likely sign that the map returned will be the same custom type you gave it, since all custom maps must implement assoc
Is there a common utility to deal with something like a bunch of predicate?
functions and whether or not they're all true? Basically like an and
operation that just takes in a bunch of predicates
Hello, there! I have recently spent some time digging into the Clojure gRPC story because I felt like putting it into a bot of mine (completely unnecessary, but why not?! 😄 ) to try some different things out. There a few resources out there for getting started, but most are somewhat dated. Would folks be interested in a repo with a minimal setup in it for exploring gRPC in Clojure? I can carve what I have out and clean it up a bit, put it in a repo, and write a little bit in the readme if folks are interested.
I can't un-recommend it enough. Protobuf is just wrong, never mind rpc being a mess If this still doesn't convince you check out a library like appsflyer/pronto for a decent-ish API to protocol buffers
Sheesh, ok. I kinda liked the idea of just “calling functions” from a client. My bot is called from a golang service
There's a pretty strong aversion to rpc in the clojure world, I'm just being unoriginal (that after implementing and scrapping to rpc libraries)
calling a function in another place is a nice way of making a distributed object
right, yes. I can see why modeling things that way would be more the Clojure way. I will be honest, I have passing familarity with what CQRS is via a rails gem I used in the past and playing around with elixir but by no means understand it well or why its good. I guess I have some homework to do!
you can send commands as data, way cooler and clojure-y-er than invoking a remote method
I don't think there's anything wrong with RPC, but gRPC is a bit more annoying because it isn't self-describing.
What I would do is use a Java gRPC client, and just use that from Clojure. Still super easy, just that yes, Clojure tend to prefer data, and data is self-describing, but if you've got a GO server you want to call, nothing wrong with that.
Right. It's the other way around. Effectively, I have a bot/server that does a bunch of stuff that is written in golang. I want to write a bunch of new functionality in Clojure but keep the golang part in place. gRPC seemed like a way to write the bot with two languages in a more deeply integrated style. This is mostly for learning Clojure and doing this in an idiomatic Clojure way is preferable. So mostly I am trying to get Go code and Clojure code to integrate well together. Right now the Clojure code does not have its own database (since it is not persisting data yet), but it will.
I see, so you want to expose API endpoints from the Clojure code so that golang calls them? And thought of exposing gRPC APIs for that?
Yes, correct
Ok well, ya that's a lot more annoying haha. There's no official Clojure support from Google for protoc to generate a Clojure server. I'm not sure if someone maintained their own well maintained and up to date. I found this: https://protojure.readthedocs.io/en/latest/ which seems to have commits from this year, but it says Ring and Compojure support isn't included, only Pedestal. So like serving gRPC I'd say is not well supported in Clojure. If I really had to do it, I would probably generate a Java server with protoc, and wrap my gRPC endpoint in Java shims that delegates to Clojure functions for their implementation.
But you'll probably be better served with just exposing some standard REST APIs from Clojure and using those from Go. I'm sure it's relatively straightforward as well from go to call a Rest API, probably easier to call a Rest API from Go then to serve a gRPC endpoint from Clojure.
Right, yes. Haha
I should prob put this book away for a bit
But in all seriousness, this was for learning so it def seems like learning something else with Clojure would be time better spent
Ya, I would say, go with gRPC if you have to because you need to integrate with a bunch of micro-services that all use gRPC to talk to each other already and all that, but its going a bit out of the way with Java shims, not hard, but a bit not as fun from a Clojure point of view.
Hi, I'm working on a codewars problem, the problem is to evaluate RPN. I have the code working that solves the problem but I'm failing the tests, e.g.
(deftest reverse-notation
(is (= (calc "") 0))
(is (= (calc "3") 3))
(is (= (calc "3.5") 3.5))
(is (= (calc "1 3 +") 4))
(is (= (calc "1 3 *") 3))
(is (= (calc "1 3 -") -2))
(is (= (calc "4 2 /") 2)))
Problem is my result is a double (since 3.5
is a double), and the tests expect sometimes a double and sometimes an int.
Is this just a known way to make this work, I'm thinking I will have to divide by 1 and check for remainder, and if no remainder cast it to an int. This seems hacky and there must be a better way?my guess is the writer of the test expects you do use something like read-string to parse numbers
I did this to make the tests pass
(defn convert-result [n]
(if (zero? (mod n 1)) (int n) n))
(defn calc [expr]
(if (= "" expr)
0
(->> (str/split expr #" ")
(map tokenize)
(evaluate-rpn)
(convert-result))))
and if you use read-string and clojures operators you will get the behavior expected in the test
read (or read-string) will return an int when reading 1 and a double when reading 1.0, and those propagate through +, /, etc
it is complicated, I generally avoid using read unless I am specifically reading edn
but that is part of the reason I think it is a bad test, it leads to do the (easier) wrong thing
Can you go the other way and have your calculator only support floats?
floats still fail the tests as it expects -2 and I'm giving it -2.0 for example, or it expects 3 and my result is 3.0
Hi,
I've written minesweeper in clojurescript and re-frame.
https://github.com/stuartstein777/cljs-minesweeper
I'd really appreciate if someone who knows re-frame and CLJS could have a quick glance and tell me what things I'm doing that are wrong.
It works (to the best of my limited testing). But I don't know if I'm doing the re-frame stuff correctly or not. I don't have a lot of experience with re-frame at all (or front end at all). I mean, I'm using svg to show numbers because I couldn't get the css to work to scale based on board size, but that's an aside). If anyone could look and say "no, dummy you are doing foo
wrong, you need to read bar
about how to do foo
properly" I'd be really grateful!
Don't worry about hurting my feelings if its all just not clojurey at all 🙂 I'll take it all as a learning experience.
I think the convention is just that impl means implementation and not public api
so as a consumer of a library, you should not be calling those
Ah, okay. There's not much more to it than that? Is it a convention from Java or just a Clojure thing?
more Clojure
since namespaces and vars are inherently available, this is a convention to mark "public"-ness
Clojure's encapsulation convention, I guess you could say... And it looks like there is no particular mapping between "public" and impl namespaces? It's pretty much organized however?
Thanks @U064X3EF3.
@UPWHQK562 Sometimes the "implementation" leaks out in libraries, such as tools.logging
which expects you to know about and use the various logger factory functions in its .impl
namespace https://github.com/clojure/tools.logging#selecting-a-logging-implementation (I do not like this).
@U04V70XH6 Thanks for pointing that out. It makes sense given it's just a convention without any enforcement by the compiler or runtime.