Hello! Is there any way to customize repl prompt in rebel-readline?
Tried some ways, some tricky like
$ clojure --repl
Clojure 1.10.1
user=> (alter-var-root
#'clojure.main/repl-prompt
(fn [_]
(fn [] (printf "my-prefix-%s=> " (ns-name *ns*)))))
#object[user$eval1$fn__137$fn__138 0x74cadd41 "user$eval1$fn__137$fn__138@74cadd41"]
user=> (clojure.main/repl-prompt)
my-prefix-user=> nil
user=>
but as you see it doesnt work...Read the docstring of clojure.main/repl
Oh not sure rebel readline will compose well with that
starting internal repl in parent one is not what i need unfortunatelly. here is some useful way https://insideclojure.org/2020/02/11/custom-repl/ but not related to rebel-readline
actually I dont need rebel, but any way for starting repl with customized prompt and which writes its input echo as a regular output stream (like rebel and repl-y does, but not raw clojure / clj)
for lein nRepl repl-y does it, but for clojure-cli I didn't find a way yet
Sure. Read the docstring for clojure.main/repl. You can give your own eval function which can write to a file and the. Evaluate.
I wrote one that saves all forms to a database.
Do you suggest to: stty -echo start my own main/repl with adding echo before :eval and my custom prompt ? Sounds like a plan, I'l try it, but not sure if it fits
I’m not sure I understand what you mean by echo. I thought you needed to have all repl input saved to a file. “Echo the input into a file”. That may not be what you meant
Definitely not. I want • terminal repl client, writes its input echo in a standart out (like repl-y & rebel, not like clojure & clj) • having customized prompt in this case
not exactly. Like this lein repl > .tmp
- compare with clj > .tmp
I need repl as a output stream produser with custom prompt and all the echo in stdout (like lein but not like clj)
λ clj -M -e '(clojure.main/repl :prompt (fn [] (print "my.prompt=> ")) :eval (fn [code] (spit "/tmp/input.txt" code) (eval code)) :print (fn [ret] (spit "/tmp/output.txt" ret) (prn ret)))'
my.prompt=> (inc 1)
2
my.prompt=>
λ cat /tmp/input.txt
(inc 1)⏎
λ cat /tmp/output.txt
2
like this?yep, but with sending all to ppipe, even echo input ) now I,m trying to play with expect
on it
All right, I don't understand what you're trying to do, but I'm pretty sure you can do it by starting a socket REPL, making a VS Code thing that connects to it, then calls clojure.main/repl
to do it. 😛
Yep, with socket or nRepl seems to be so 🙂 But I started with linux pipe 'middlewares' and for now going to play with them 😁 Thanks alot anyway!
does using clojure
(not readline wrapped) instead of clj
(readline wrapped) help you here? I definitely wouldn't use the readline wrapped version of a program with expect, if there's an option
this reminds me of my long standing threat to make expect
for clojure :D
Yesterdays night I solved the problem - see Clojure CLI section in readme https://github.com/Ivana-/bb-clj 🙂
lein's repl-y works as it describes, and lein profile can set repl-options including prompt function. Now I'm searching solution for clojure cli (without lein)
I am not sure about this part: https://clojure.org/guides/core_async_go#_unsupported_constructs_and_other_limitations_in_go_blocks Why doesn’t (go (map <! some-chan))
work?
as I understand it, the answer is that go
is a code rewrite that inverts <!
, >!
etc. so that surrounding code is made into callbacks on channel objects with the channel op as the sequence point / split point. using a split point token as a first class function is nonsensical (unless maybe you have call/cc which we don't have)
I worded that very obscurely. go
rewrites your block of code, and everything outside / before a call to <!
, >!
, alts!
etc. gets turned into a callback on the incoming channel, and everything inside / after that call becomes a second callback attached to the channel, activated after the data is available.
I don't think I ever would have made sense of it if I hadn't previously learned continuation passing style (a tedious way to write code, but a very useful transform for compilers)
It also claims just below saying that: However, other Clojure constructs, such as `doseq` do not allocate closures internally. Not sure about the closure here.
When does map create functions?
I see I get it.
Like this?
λ clj -M -e '(clojure.main/repl :prompt (fn [] (print "my.prompt=> ")) :eval (fn [x] (prn x) (eval x)))'
my.prompt=> (inc 1)
(inc 1)
2
my.prompt=> (dec 2)
(dec 2)
1
my.prompt=>
Hello there, I'm trying to get into core.async and copy and paste code from some example leads to an error:
Exception in thread "async-thread-macro-1" Exception in thread "async-thread-macro-2" clojure.lang.ArityException: Wrong number of args (2) passed to: clojure.core.async/fn--12774
at clojure.lang.AFn.throwArity(AFn.java:429)
at clojure.lang.AFn.invoke(AFn.java:36)
at idanko.progsolutions.clojure.core_async.thread_macro$eval16837$fn__16838.invoke(NO_SOURCE_FILE:12)
at clojure.core.async$thread_call$fn__12905.invoke(async.clj:484)
at clojure.lang.AFn.run(AFn.java:22)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
clojure.lang.ArityException: Wrong number of args (1) passed to: clojure.core.async/fn--12786
at clojure.lang.AFn.throwArity(AFn.java:429)
at clojure.lang.AFn.invoke(AFn.java:32)
at idanko.progsolutions.clojure.core_async.thread_macro$eval16837$fn__16841.invoke(NO_SOURCE_FILE:16)
at clojure.core.async$thread_call$fn__12905.invoke(async.clj:484)
at clojure.lang.AFn.run(AFn.java:22)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
what i'm trying to evaluate is:
(ns idanko.progsolutions.clojure.core_async.thread-macro
(:require [clojure.core.async :refer [chan <!! >!! thread]]))
(let [c chan]
(thread
(dotimes [x 3]
(<!! c x)
(println "Put: " x)))
(thread
(dotimes [x 3]
(println "Take " (>!! c)))))
where is a catch?<!!
and >!!
are the wrong way around. <!!
is take and takes one arg, >!!
is put and takes two args.
ended, my bad
ok, also chan is not called as a func
Oh, yep. :thumbsup::skin-tone-2:
Definitely not a clojure related question, but folks are really good here so. I have three labels: amusement, calm and energetic. I get a sets of words like: Set1 = {Cloud Sky People in nature Plant Flash photography Happy Shorts Grass Leisure Recreation} Set2 = {Plant Green Natural landscape Natural environment Branch Tree People in nature Shade Wood Deciduous} I want to classify these group of words into one of the labels. What do you guys think? Set1 should be labelled energetic and Set2 should be labelled calm. What do you guys think?
Perhaps more suited for #off-topic
I’ve noticed Sublime Text 4 is out and I do remember somebody with a link about setting up Clojure with SB4. Does anybody have the link somewhere?
Probably not the exact thing you're looking for, but I'm obligated to plug my thing. 😛 https://tutkain.flowthing.me/
Does it work with ST4?
It only works with ST4.
Oh nice, in such case I’ll give it a try
I've managed to confuse myself with protocols and records, again. I have a protocol defined in a namespace that's extended to a record defined in another namespace as follows: core/store.clj:
(ns core.store)
(defprotocol Store
"An abstraction for a persistent data store."
(read-records [this] "Reads records from a Store.")
(write-records [this records] "Writes records to a Store."))
stores/in-memory-store.clj:
(ns stores.in-memory-store
(:require [core.store]))
(defrecord InMemoryStore []
core.store/Store
(core.store/read-records [this] [1 2 3]) ; A: fully-qualified method name
(write-records [this records] :success)) ; B: non-qualified method name
Both notations A and B for referring to the methods defined in protocol Store
seem to be valid (i.e., they both compile) but Cursive indicates that notation A is an error (i.e., it puts a squiggly line under the qualified method name, core.store/read-records
) but shows the correct docstring (however, it fails to show the docstring for the "correct" notation B 🤷). Now my question is, which notation is the canonical one when referring to a protocol method defined in another namespace in the context of defrecord
? If I understood correctly what happens with protocol definitions under the hood, they just def
a bunch of regular Var
s (with some metadata) and we should just refer to them as we would with any other Var
s but I was confused by the fact that we can in fact refer to them with and without the their namespace (or alias) when extending a record. Is there something special about defrecord
when it comes to extending a protocol?I’d like to get away from VSCode if possible
for battery reasons mostly
Cool. It's in alpha and not many people have used it so far, so you'll probably come across some issues. In that case, please don't hesitate to DM me and I'll look into it.
👍
The second is correct
Because you are referring to the name in the context of the given protocol, you don't need to disambiguated via namespaces
do people have a generally positive feeling about core.cache?
I'm looking at writing some caching algos for ClojureScript, and wondering if I should push on trying to get a release of core.cache that at least has the protocols in CLJS, or if I should just release my own standalone lib
That's interesting. Do you know of anything (documentation, articles, blog posts, mailing lists messages, etc.) that you can point me at that discusses these two different notations? Thanks!
I’ve never seen it discussed—in part because I think it’s not often that it occurs to people to try it 😄
but hang on, I think I found something in the compiler about this
Exactly, I just "discovered" this today despite the fact that I've been using Clojure for more than 5 years. 😅
So defrecord
compiles down to deftype*
. This appears to be where deftype*
compiles the method forms. You can see at line 8437 that the emitted method name is just the name
portion of the parsed symbol.
(it calls dotname.name
)
I’m no expert on this part of the compiler, but it appears that any namespace portion is just dropped during compilation.
You can probably confirm this trivially with a decompiler.
Just my own opinion (I’ve only talked to people I’ve worked with about it), but I have little use for it as-is.
I consider the cache protocol private.
Because: when I usually want a cache I either want to spare compute resources or spare load on downstream resources. core.cached doesn’t coordinate value initialization, so it leaves both of those use cases unsatisfied.
It seems okay when you’re looking to shave 10ms on a large volume of calls. But if you want to save 30s of compute or a 2gb network trip on a low volume of calls, it’s useless.
Nice! I'll take it from here and dig a little bit. Thanks, @potetm!
I have also never seen core.cache used without core.memoize, because no one wants an immutable cache
Do you think it’s to do with it being immutable per se? Non-coordinated is the primary issue as I see it.
"coordinate value initialization" by which you mean it doesn't handle multiple concurrent processes getting a miss and then fetching/computing the result?
in the case of CLJS it's actually convenient that it's immutable, since there tend to be different special atom-like containers used amongst different UI frameworks
sounds like it may not ubiquitous enough for there to be a big benefit to having a community-wide protocol for it
so I won't waste my time trying to push for a CLJS protocol 🙂
Hello. Recently I asked some weird questions and maybe there was not clear what I want. I try to explain in another words - any can make a little experiment: compare `lein repl > .tmp` with `clj > .tmp` I need the first behaviour from clojure cli (I mean echo in stdout) - is it possible? And also customized prompt. Thanks.
when i run lein repl > .tmp
i never see what i'm typing, but all output is sent to the file. is that what you want?
Exactly yep!
And you will see in file what are you typing
have you seen script
?
you can record the entire terminal session
Not yet, but I'l google about it, thanks
not clear to me if you don't want to see what you're typing (sounds very strange to me) or are just willing to not see what you are typing to have a full repl history saved
I'l see what I'm typin, cause I'l redirect repl stdout not to file but to my custom consume-visualizer. But in order to do it I need all in the pipe
is there a reason you need to specifically use stdout?
clojure has protocols for working with remote REPLs programmatically that might be more useful
Yep, you mean nRepl and sockets. But I want universal common easy solution as a consumer of all terminal repl data
I'm curious why terminal though?
cause it's common, universal, and seems like a good point to interact with repls running either with lein/repl-y either with clojure cli or somethig else
and not need to connect via nrepls ports and implement nrepl protocol (it is easy in clojure but not in clojurescript)
i don't see a solution in my head but i feel like there's a way to be clever with a socket repl and a wrapper around the socket. perhaps nc can mirror socket traffic to a file?
I would think socket REPL would be the most common; it comes with clojure.core, you don't need shell access to use it (i.e. I can run clojure in a container or remote server), and it is relatively well supported compared to consuming the REPL via a shell buffer
it's also cross platform; you don't need to worry as much about windows
Thanks, I didn't deeg deep into socket repl yet, maybe it would be a good way. Seems that it is time to play with it 🙂
it would also be helpful if you say your end goal without any implementation details "I want to easily save entire repl history for human consumption" or something along those lines
yw. I've been down the same path a couple times. if you don't want to take on nREPL or any other additional dependencies, prepl might be a good starting point since it's bundled with clojure
@ivana fwiw, I don’t know of any full-time clojurists who use the terminal repl.
final goal is to write my own clojure plugin for vscode
makes sense as a starting point perhaps, but it’s only universal in the sense that everyone has access, not that everyone uses it.
@ivana why write your own? There is #calva based on nREPL and there is clover (#chlorine-clover ) based on the socket REPL
I already implemented it and it works as I wish on lein repl, but now I want to expand it on clojure cli too
@borkdude cause they both are breaks vscode behaviour and calva has a lot of cons (unfortunatelly)
@ivana may I ask how Clover, for example, breaks VSCode behaviour? Or what are you trying to do with your own plug-in?
@mauricio.szabo give me 5 mins - i"l try to install clover and reproduse
(I'm really curious, to be honest, because Clover does so little 😄)
@mauricio.szabo • install Clover • set vscose setting "remove trailing whitespaces on file saving" • look that with Clover enabled it is not working The same thing with Calva, Calva-fmt etc.
That's quite bizarre - there's nothing specific about this setting on Clover... unless the formatter is conflicting with VSCode's defaults
Can you reproduce it on your vscode? Or it is my local bug only?
I'm opening Codium right now 🙂
Ok, it's not only you: I'm seeing the same behavior.
Yep, and for me it's easier to write my own plugin than to ask authors of existed ones to make fixes 🙂 And sorry, guyes, I know its not an Clover or even editors channel, maybe will be better to continue Clover discussion in specified one 🙂
I have to be honest: I have absolutely no idea why this happens. I disabled Clover, "trailing whitespaces" works. Enable it, stop working. I removed all subscriptions, and it still don't work. There's a "formatter" on Clover, disabled that, didn't work.
I'll have to be honest with you: VSCode API is quite a pain 😄
If you want to write your own plug-in, go ahead, but there are lots of edge-cases that are quite difficult to get it right (or even at all)... that's one of the reasons for my library repl-tooling
- so I can test some of these edge-cases without depending on the VSCode API.
BTW: found the bug, will issue a fix 😄
Thanks, I'm already met some of vscode specifics 😁 But anyway I'm already wrote my plugin and I use it on my work (just for lein repl-y). I think if someone interested I can make a little stream about it, the reasons and the result. What do you think?
I am quite interested, to be honest 🙂
So, then let me do some tryes with clojure cli repls, and then I ask community if any else is interested and will make a little stream 🙂 Thanks for your support!
Yes, I seem to recall running across this before, and being surprised that you can put whatever you want in the namespace part of the symbols.
@ivana You could certainly share your journey in #vscode (which isn’t #calva specific) or even in #editors if you end up integrating this into other editors.
@seancorfield thanks, I'l announce some points when it will be more ready.
Why does clojure.core.async/map
call java.util.Arrays/copyOf
before adding the array to the results channel? Why not just use rets
directly?
Just curiosity. Thought it has something to do with memory and JVM.
@p-himik the rets array get filled with the map over each first item from each chan, then overwritten with the result from each second item from each chan. Without the array copyOf the result you'd get would get overwritten 'underneath' you
Oh, duh! Thanks!
I got mentally stuck in my own use-case of a/map
where I have N channels of 1 item each.
Place-oriented programming is the tar pit (but I understand the need for it as an optimization technique).