Fork me on GitHub
#clojure
<
2021-05-22
>
ivana01:05:30

Hello! Is there any way to customize repl prompt in rebel-readline?

ivana01:05:22

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_[email protected]"]
user=> (clojure.main/repl-prompt)
my-prefix-user=> nil
user=> 
but as you see it doesnt work...

dpsutton01:05:34

Read the docstring of clojure.main/repl

dpsutton01:05:14

Oh not sure rebel readline will compose well with that

ivana01:05:26

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

ivana02:05:42

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)

ivana02:05:34

for lein nRepl repl-y does it, but for clojure-cli I didn't find a way yet

dpsutton02:05:53

Sure. Read the docstring for clojure.main/repl. You can give your own eval function which can write to a file and the. Evaluate.

dpsutton02:05:03

I wrote one that saves all forms to a database.

ivana02:05:29

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

dpsutton02:05:03

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

ivana02:05:56

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

flowthing05:05:01

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=>

ivana19:05:48

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)

flowthing20:05:50

λ 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?

ivana20:05:35

yep, but with sending all to ppipe, even echo input ) now I,m trying to play with expect on it

flowthing20:05:20

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. 😛

ivana20:05:29

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!

noisesmith17:05:06

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

noisesmith17:05:21

this reminds me of my long standing threat to make expect for clojure :D

ivana17:05:05

Yesterdays night I solved the problem - see Clojure CLI section in readme https://github.com/Ivana-/bb-clj 🙂

ivana02:05:26

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)

introom03:05:20

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.

introom03:05:23

When does map create functions?

introom03:05:42

I see I get it.

noisesmith17:05:18

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)

noisesmith17:05:08

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.

noisesmith17:05:15

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)

Illia Danko15:05:07

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?

flowthing15:05:28

<!! and >!! are the wrong way around. <!! is take and takes one arg, >!! is put and takes two args.

👍 3
Illia Danko15:05:15

ended, my bad

Illia Danko15:05:00

ok, also chan is not called as a func

flowthing15:05:24

Oh, yep. :thumbsup::skin-tone-2:

zendevil15:05:26

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?

p-himik16:05:39

Perhaps more suited for #off-topic

vncz17:05:21

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?

flowthing17:05:08

Probably not the exact thing you're looking for, but I'm obligated to plug my thing. 😛 https://tutkain.flowthing.me/

vncz17:05:59

Does it work with ST4?

flowthing17:05:07

It only works with ST4.

vncz17:05:21

Oh nice, in such case I’ll give it a try

vncz17:05:30

I’d like to get away from VSCode if possible

vncz17:05:40

for battery reasons mostly

flowthing17:05:53

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.

salam17:05:26

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 Vars (with some metadata) and we should just refer to them as we would with any other Vars 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?

hiredman17:05:15

The second is correct

hiredman17:05:06

Because you are referring to the name in the context of the given protocol, you don't need to disambiguated via namespaces

salam17:05:39

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!

potetm17:05:08

I’ve never seen it discussed—in part because I think it’s not often that it occurs to people to try it 😄

potetm17:05:42

but hang on, I think I found something in the compiler about this

salam17:05:01

Exactly, I just "discovered" this today despite the fact that I've been using Clojure for more than 5 years. 😅

potetm17:05:17

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.

potetm17:05:25

(it calls dotname.name)

potetm18:05:06

I’m no expert on this part of the compiler, but it appears that any namespace portion is just dropped during compilation.

potetm18:05:14

You can probably confirm this trivially with a decompiler.

salam18:05:33

Nice! I'll take it from here and dig a little bit. Thanks, @U07S8JGF7!

👍 3
cfleming20:05:34

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.

🤷 3
lilactown17:05:12

do people have a generally positive feeling about core.cache?

potetm18:05:13

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.

potetm18:05:17

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.

potetm18:05:19

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.

lilactown18:05:19

"coordinate value initialization" by which you mean it doesn't handle multiple concurrent processes getting a miss and then fetching/computing the result?

✔️ 3
lilactown17:05:40

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

dpsutton18:05:12

I consider the cache protocol private.

hiredman18:05:08

I have also never seen core.cache used without core.memoize, because no one wants an immutable cache

potetm18:05:47

Do you think it’s to do with it being immutable per se? Non-coordinated is the primary issue as I see it.

lilactown18:05:08

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

lilactown18:05:11

sounds like it may not ubiquitous enough for there to be a big benefit to having a community-wide protocol for it

lilactown18:05:32

so I won't waste my time trying to push for a CLJS protocol 🙂

ivana19:05:23

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.

dpsutton19:05:16

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?

ivana19:05:39

Exactly yep!

ivana19:05:14

And you will see in file what are you typing

dpsutton19:05:30

have you seen script?

dpsutton19:05:44

you can record the entire terminal session

ivana19:05:57

Not yet, but I'l google about it, thanks

dpsutton19:05:28

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

ivana19:05:29

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

lilactown19:05:00

is there a reason you need to specifically use stdout?

lilactown19:05:19

clojure has protocols for working with remote REPLs programmatically that might be more useful

ivana19:05:41

Yep, you mean nRepl and sockets. But I want universal common easy solution as a consumer of all terminal repl data

lilactown19:05:36

I'm curious why terminal though?

ivana19:05:57

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

ivana19:05:10

and not need to connect via nrepls ports and implement nrepl protocol (it is easy in clojure but not in clojurescript)

dpsutton19:05:42

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?

lilactown19:05:07

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

lilactown19:05:34

it's also cross platform; you don't need to worry as much about windows

ivana19:05:00

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 🙂

dpsutton19:05:51

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

lilactown19:05:22

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

potetm19:05:34

@ivana fwiw, I don’t know of any full-time clojurists who use the terminal repl.

ivana19:05:42

final goal is to write my own clojure plugin for vscode

potetm19:05:12

makes sense as a starting point perhaps, but it’s only universal in the sense that everyone has access, not that everyone uses it.

borkdude20:05:03

@ivana why write your own? There is #calva based on nREPL and there is clover (#chlorine-clover ) based on the socket REPL

ivana20:05:12

I already implemented it and it works as I wish on lein repl, but now I want to expand it on clojure cli too

👍 3
ivana20:05:29

@borkdude cause they both are breaks vscode behaviour and calva has a lot of cons (unfortunatelly)

mauricio.szabo20:05:23

@ivana may I ask how Clover, for example, breaks VSCode behaviour? Or what are you trying to do with your own plug-in?

ivana20:05:19

@mauricio.szabo give me 5 mins - i"l try to install clover and reproduse

mauricio.szabo20:05:26

(I'm really curious, to be honest, because Clover does so little 😄)

ivana20:05:15

@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.

mauricio.szabo20:05:20

That's quite bizarre - there's nothing specific about this setting on Clover... unless the formatter is conflicting with VSCode's defaults

ivana20:05:34

Can you reproduce it on your vscode? Or it is my local bug only?

mauricio.szabo20:05:43

I'm opening Codium right now 🙂

mauricio.szabo20:05:45

Ok, it's not only you: I'm seeing the same behavior.

ivana20:05:02

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 🙂

mauricio.szabo20:05:48

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.

mauricio.szabo20:05:42

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.

mauricio.szabo20:05:52

BTW: found the bug, will issue a fix 😄

ivana20:05:42

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?

mauricio.szabo20:05:41

I am quite interested, to be honest 🙂

ivana20:05:23

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!

seancorfield23:05:21

@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.

ivana23:05:34

@U04V70XH6 thanks, I'l announce some points when it will be more ready.

3
p-himik23:05:30

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?

raspasov00:05:43

From a brief look at the code, rets acts like many “boxes” that receives different values. They are used in the (go-loop …) in the same fn. So I believe they actually need to be different instances rather than the same instance. (but I could be misunderstanding the code)

raspasov00:05:40

done are a vector of callback functions that each take ret

raspasov00:05:13

I feel like I’d need to spend a bit of time with that code to understand the intent there. I might be totally off. Is the copyOf causing a problem for you?

p-himik08:05:45

Just curiosity. Thought it has something to do with memory and JVM.

thegeez12:05:29

@U2FRKM4TW 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

👆 3
p-himik12:05:20

Oh, duh! Thanks! I got mentally stuck in my own use-case of a/map where I have N channels of 1 item each.

raspasov16:05:45

Place-oriented programming is the tar pit (but I understand the need for it as an optimization technique).

3