beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
grazfather 2021-02-16T00:47:43.190900Z

it’s worse than all of these. Sorry for setting you guys on a wild goose chase

grazfather 2021-02-16T00:47:54.191100Z

I had opened the wrong stack trace 🤦

grazfather 2021-02-16T00:49:25.191300Z

The problem is that I am doing a format "…%.2f" (api call) and when parsing the response json if the temperature happens to be exactly zero then the type is not a float

2021-02-16T00:54:10.191500Z

glad you found the actual problem!

grazfather 2021-02-16T01:04:48.191700Z

Thank you!

Rowan Barnard 2021-02-16T05:51:17.195700Z

Hi everyone, I've been using Clj commandline tools in Powershell on Windows and I entered the following into the commandline: user=> (require '[reader.snake :refer :all]) Execution error at user/eval213 (REPL:1). No namespace: reader.snake user=> (require '[examples.snake :refer :all]) nil user=> PS C:\Users\celap\Downloads\shcloj3-code\code> clj Clojure 1.10.2 user=> (require '[reader.snake :refer :all]) nil

Rowan Barnard 2021-02-16T05:52:39.197200Z

Oops that was meant to be code blocked, anyway I am wondering why my first require of reader.snake didn't work but almost immediately after it did work

dpsutton 2021-02-16T05:52:53.197400Z

have you got a link to the repo?

dpsutton 2021-02-16T05:53:25.198300Z

you can create namespaces programmatically so its possible examples.snake does something like this

Rowan Barnard 2021-02-16T05:53:49.198900Z

Ah I'm pretty beginner so not really understanding the repo thing - the code is on the page for the book in a zip file I will just link it

Rowan Barnard 2021-02-16T05:55:12.200600Z

There's a deps.edn in the folder root that I added paths to src/reader and src/examples in

Rowan Barnard 2021-02-16T05:55:40.201500Z

Because it wasn't seeing those earlier when I tried requiring in code from the book

seancorfield 2021-02-16T05:57:00.202700Z

That's why you see the behavior above.

seancorfield 2021-02-16T05:57:35.203900Z

You tried to require a ns whose file wasn't on the path. You updated deps.edn. You need to restart your REPL to pick up those changes.

2021-02-16T11:31:43.214500Z

I am not sure if the following explains it, but if you do a require in a REPL that fails due to an error, there are some kinds of errors that still do cause the namespace to be created, and for the namespace to be added to a *loaded-libs* Clojure var. If you then do a requireagain with no special options, it will check *loaded-libs*, see the namespace is there, and not attempt to read the file again, unless you do a require with an option to force it to read the file again, e.g. (require 'examples.snake :reload), if I recall correctly.

2021-02-16T11:32:38.214700Z

*loaded-libs* is there to prevent the otherwise common occurrence that later namespaces will require namespace foo, causing foo to be loaded over and over again, including transitively everything that foo requires.

Rowan Barnard 2021-02-17T01:18:32.264800Z

Ah I think that might be it then - I did try to require the reader.snake file but it failed because I'd accidentally left some test code in the file but had deleted the defs for it, so it was like a symbol couldn't be found error thrown from the require, then I deleted the test code from the file, tried the require again which is where the code snippet I pasted starts from, it failed to find the namespace which confused me as it was working fine the previous day and I'd added paths to the folder in my deps (which I apparently don't even need) so I tried requiring the book's examples.snake (which is basically a copy of the code in a parallel folder) and it worked fine so I scratched my head, reloaded Clj and then the require of reader.snake worked fine, so yeah sounds just like what you describe, so that must be it, thank you, and thank you also Sean 😉

Rowan Barnard 2021-02-17T01:24:26.265Z

This probably explains many of the other times where I've had problems with not being able to 'see' namespaces/files where I could've sworn it was working fine earlier, if anyone's writing books for Clojure beginners I think this is something that should definitely be mentioned 🙂

seancorfield 2021-02-17T01:32:43.265200Z

This sort of thing is why it is so much better to work within an editor with a connected REPL, and then you aren't trying to type stuff into the REPL -- you're editing files and evaluating it directly into the running REPL.

Rowan Barnard 2021-02-17T01:34:58.265400Z

Ah OK I see, many beginners' books if not the majority seem to assume working from the REPL though, so I think it would be a good idea to warn beginners about something like this

Rowan Barnard 2021-02-17T01:37:55.265600Z

I learned something new though and reduced something magical to something I can understand, so feeling good thanks guys, wish you all a beautiful day 😉

seancorfield 2021-02-17T01:48:34.265800Z

Yeah, I think a lot of authors don't want to deal with the vast array of editors and plugins and getting those setup and configured.

seancorfield 2021-02-17T01:49:12.266Z

Brave&True takes beginners through Emacs/CIDER setup -- which I don't think is a good idea (unless the beginner is already using Emacs perhaps!).

seancorfield 2021-02-17T01:50:02.266200Z

Maybe as more and more developers use VS Code, we'll start to see material that assumes VS Code (& Calva). That's certainly a pretty good beginner setup and the maintainer team is super-responsive and helpful.

seancorfield 2021-02-17T01:50:29.266400Z

What editor are you using @flyingpython? (I'm sure you've said before but I have a goldfish brain)

Rowan Barnard 2021-02-17T01:52:09.266600Z

Ah yeah I'd say so, the VS Code numbers I saw on the last dev survey were huge, it seems to be rapidly approaching an industry standard, yeah I'm using Atom with your old REBL and Chlorine setup still and I occasionally use VS Code with Calva

Rowan Barnard 2021-02-17T01:53:09.266800Z

I see Calva is getting some kind of interoperability with Clover now? So maybe I can use that setup with your new Clover config and Reveal?

seancorfield 2021-02-17T01:53:41.267Z

Yeah, I'm using Calva for everything except actual REPL eval stuff -- which I'm using Clover for. And I'm using Reveal.

seancorfield 2021-02-17T01:54:09.267200Z

And that setup, for me, is identical on macOS (my work desktop) and Windows 10/WSL2/Ubuntu which is my personal laptop.

Rowan Barnard 2021-02-17T01:54:18.267400Z

Oh that sounds cool, yeah I'll try switch to that sometime

seancorfield 2021-02-17T01:54:49.267600Z

https://github.com/seancorfield/vscode-clover-setup and https://github.com/seancorfield/dot-clojure (in particular for the Reveal extras in dev.clj).

Rowan Barnard 2021-02-17T01:55:36.268100Z

Thanks for the links, bookmarking them now

seancorfield 2021-02-17T01:56:39.268300Z

Installing Calva meant I could simplify my VS Code setup since it has its own paredit/rainbow parens etc -- so I stripped out three or four extensions after adding Calva. Then just edited Calva's settings to hide the nREPL UI (so I can use Clover's stuff instead).

seancorfield 2021-02-17T01:57:20.268500Z

Also, the hot keys for Atom/Chlorine work for VS Code/Clover if you follow my setup, so you don't even have to learn new key bindings 🙂

Rowan Barnard 2021-02-17T01:57:21.268700Z

Ah OK so the hide REPL ui is the only setting thing you have to change in Calva when using it with Clover?

seancorfield 2021-02-17T01:57:46.268900Z

Yup.

Rowan Barnard 2021-02-17T01:58:04.269100Z

Ah that is cool because I've grown accustomed to your keybindings and going back to Calva's felt really wrong 😛

seancorfield 2021-02-17T02:00:10.269300Z

Do you switch between multiple machines at all?

Rowan Barnard 2021-02-17T02:01:02.269500Z

No I just have the one desktop machine which may be close to 10 years old now 😂

Rowan Barnard 2021-02-17T02:01:19.269700Z

It is an amd phenom 2

Rowan Barnard 2021-02-17T02:01:55.269900Z

From back when the very first quad core CPUs were hitting the market

seancorfield 2021-02-17T02:12:59.270100Z

Ah, OK. I asked because VS Code can automatically sync all your settings and all your extensions between all your machines 🙂 which I found very helpful when I went to set it up on a second machine (and it basically set itself up to match my first machine).

Rowan Barnard 2021-02-17T02:13:45.270300Z

Oh yeah that's cool 🙂

2021-02-16T05:57:36.204Z

Hi, after tried several times, it still not connected, i figure out that i need 1. to define my :host-prefix "//FBI-HIDEOUT\\JUST_INTO_DS" 2. change my IPall port = 1433 3. make an inbound firewall for port 1433 (Instead I also turned my firewall off) but still giving an error, please help address where's the mistake? I'm using SQL express for an exercise btw.

Execution error (SQLServerException) at com.microsoft.sqlserver.jdbc.SQLServerException/makeFromDriverError (SQLServerException.java:234).
The TCP/IP connection to the host FBI-HIDEOUT, port 1433 has failed. Error: "Connect timed out. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.".

Rowan Barnard 2021-02-16T05:59:01.205100Z

But I had added the paths to the deps.edn yesterday and started the commandline and clj afresh today

seancorfield 2021-02-16T05:59:07.205300Z

I'm pretty sure "//FBI-HIDEOUT\\JUST_INTO_DS" is your problem.

seancorfield 2021-02-16T05:59:37.205600Z

You shouldn't be mixing \\ and // I think.

2021-02-16T06:00:33.205800Z

@seancorfield how should i write it?

2021-02-16T06:01:20.206Z

(def db-sqlserver {:dbtype "sqlserver" :dbname "AdventureWorks"
                   :host-prefix "//FBI-HIDEOUT\\JUST_INTO_DS"
                   :port "1433"
                   :user "sa" :password "123456789"})

Rowan Barnard 2021-02-16T06:02:22.206200Z

I didn't do anything else outside the terminal between typing in those different commands on the terminal so it seems a bit mysterious to me, I am sure this has happened to me before too, but I've also done a lot of silly newbie things so maybe it is just that again 😅

dpsutton 2021-02-16T06:02:44.206400Z

this repo is a little strange to me for some reason

dpsutton 2021-02-16T06:02:47.206600Z

user> (require 'reader.snake)
CompilerException java.lang.Exception: No namespace: examples.import-static, compiling:(reader/snake.clj:1:1) 
user> (require 'examples.import-static)
nil
user> (require 'reader.snake)
nil
user> 

Rowan Barnard 2021-02-16T06:04:19.206800Z

Ah yeah I think there was a mistake in the require statement in that file that I had to correct - just look at the require for the import-static and it should be obvious

Rowan Barnard 2021-02-16T06:04:44.207Z

I think it used round brackets instead of the square ones or something like that

seancorfield 2021-02-16T06:04:56.207200Z

Are you sure you need :host-prefix there? In the test suite for clojure.java.jdbc, the MS SQL test from macOS to Windows uses :host "127.0.0.1\\SQLEXPRESS" -- what is your setup with where you're running Clojure and where your MS SQL Server is running?

Rowan Barnard 2021-02-16T06:05:12.207400Z

And you may need to add the paths to the folders in the deps file as it has no paths in it

Rowan Barnard 2021-02-16T06:06:51.207600Z

I added src/examples, src/reader and src to my paths

2021-02-16T06:07:35.207800Z

my dependencies

:dependencies [[org.clojure/clojure "1.10.1"]
				 [com.layerware/hugsql-core "0.5.1"]
				 [com.layerware/hugsql-adapter-next-jdbc "0.5.1"]
				 [com.microsoft.sqlserver/mssql-jdbc "9.2.0.jre15"]
				 [mysql/mysql-connector-java "8.0.23"]
				 [honeysql "1.0.444"]
				 [seancorfield/next.jdbc "1.1.613"]]
I'm using windows 10, my MS SQL Server running from my own (not remote), i'm still practicing using SQL Express

seancorfield 2021-02-16T06:09:33.208Z

Why are you using :host-prefix? That's definitely not right (since :host will default to "127.0.0.1" and you don't want that weird string in front of that).

seancorfield 2021-02-16T06:10:51.208200Z

If the DB is running on localhost, you probably want :host "127.0.0.1\\JUST_INTO_DS" (and remove :host-prefix).

seancorfield 2021-02-16T06:11:38.208400Z

Not sure what FBI-HIDEOUT is in that...?

2021-02-16T06:13:49.208600Z

(def db-sqlserver {:dbtype "sqlserver" :dbname "AdventureWorks"
                   :host "127.0.0.1\\JUST_INTO_DS"
                   :user "sa" :password "123456789"})
still give an error
Execution error (SQLServerException) at com.microsoft.sqlserver.jdbc.SQLServerException/makeFromDriverError (SQLServerException.java:234).
The TCP/IP connection to the host 127.0.0.1, port 1433 has failed. Error: "Connect timed out. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.".

2021-02-16T06:15:59.208800Z

i'll try to make another server instead of JUST_INTO_DS

seancorfield 2021-02-16T06:17:17.209Z

That says that the JVM cannot connect to SQL Server running on localhost on the default port. Are you sure it's available on that IP address and not some other address?

seancorfield 2021-02-16T06:17:56.209200Z

I see 192.168.137.1 in that screenshot you posted.

2021-02-16T06:20:23.209400Z

i didn't make any changes, all is the default when establishing the server

seancorfield 2021-02-16T06:26:38.209700Z

The problem is that the source file src/reader/snake.clj has

(:refer examples.import-static :refer :all])
but it should be
(:require [examples.import-static :refer :all]))
Until you make that change, you cannot (require 'reader.snake)

seancorfield 2021-02-16T06:27:01.209900Z

You don't need those paths added -- the deps.edn file is correct as it stands.

seancorfield 2021-02-16T06:28:19.210300Z

Then maybe try :host "192.168.137.1\\JUST_INTO_DS" is what I'm suggesting.

2021-02-16T06:29:15.210500Z

can't as well 😭🙏 I've tried that.

seancorfield 2021-02-16T06:29:28.210700Z

Then I have no idea how to help, sorry.

seancorfield 2021-02-16T06:29:49.210900Z

You'll have to find someone who a) uses Windows and b) uses MS SQL Server.

2021-02-16T06:31:13.211100Z

Sure no problem, you've helped me look into another different way... I'll try again... thank you so much.

seancorfield 2021-02-16T06:33:08.211300Z

If you were on macOS or Linux, I'd suggest using telnet or nc to diagnose the network connectivity, outside of the JVM, but I've no idea what to suggest for Windows.

seancorfield 2021-02-16T06:34:10.211500Z

I use WSL2 for all of my Clojure development on Windows (WSL2 running Ubuntu), and I use Docker for all of my MS SQL Server testing (and Microsoft's official Docker image for SQL Server is Linux-based).

Audrius 2021-02-16T07:07:02.211700Z

yes this hangs only if javadoc opened a new browser

2021-02-16T07:48:30.211900Z

OH GOSH... imagine looking up & down, left & right, back & forth.. lol the answer is to "restart" the server... waow, worth 2 days 2 night... ahahahahaha :rolling_on_the_floor_laughing:

Rowan Barnard 2021-02-16T07:49:15.212100Z

I did already change the refer to the proper require form after receiving an error about it and then after that it couldn't find the files, a FileNotFound I think, so that's when I added the paths to the deps and then after that it worked fine for me until today when that happened with requiring the reader.snake

Rowan Barnard 2021-02-16T07:50:04.212600Z

I always seem to get weird things like this from time to time, maybe it is a caching thing again?

oly 2021-02-16T09:24:08.214100Z

if I build a jar is there a way todo the equivalent of -m app.commands I have an app with a webserver but it also has cli-matic embeded so in essence want to be able to run one of the cli-matic commands with out clj available

arielalexi 2021-02-16T12:04:28.217600Z

Is there a way to keep the nano seconds for a timestamp when using #inst?

User > #inst "2002-02-19T03:40:27.000404Z"
;; => #inst "2002-02-19T03:40:27.000-00:00"

alexmiller 2021-02-16T12:06:36.217900Z

no - the type being created there is ms precision

arielalexi 2021-02-16T12:49:46.218Z

can you reffer to more info about this?

alexmiller 2021-02-16T13:11:35.218200Z

by default, #inst makes a https://docs.oracle.com/javase/8/docs/api/java/util/Date.html which has ms resolution

alexmiller 2021-02-16T13:13:19.218500Z

you could alternately construct https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html s which have ns resolution

alexmiller 2021-02-16T13:14:44.218700Z

if you're looking for docs on #inst, see https://clojure.org/reference/reader#_built_in_tagged_literals

👍 1
2021-02-16T14:16:38.219800Z

you can start clojure.main (the repl) from any jar with clojure: java -cp my.jar clojure.main

2021-02-16T14:17:06.220Z

this won't have nice things like command line editing / history etc. but it is enough to run any code that clojure knows how to find and run

2021-02-16T14:21:30.220200Z

(ins)justin@abjection:~/foo-uber$ java -cp target/uberjar/foo-uber-0.1.0-SNAPSHOT-standalone.jar clojure.main -m foo.bar
Execution error (FileNotFoundException) at clojure.main/main (main.java:40).
Could not locate foo/bar__init.class, foo/bar.clj or foo/bar.cljc on classpath.

Full report at:
/tmp/clojure-18226576097563274172.edn
(ins)justin@abjection:~/foo-uber$ mkdir src/foo
(ins)justin@abjection:~/foo-uber$ cat > src/foo/bar.clj
(ns foo.bar)

(defn -main [& args]
  (println "OK"))
(ins)justin@abjection:~/foo-uber$ java -cp src:target/uberjar/foo-uber-0.1.0-SNAPSHOT-standalone.jar clojure.main -m foo.bar
OK
tl;dr - yes you can use -m with an uberjar

popeye 2021-02-16T14:58:31.220600Z

I have below string

Select * from table
WHERE 
 {
    a.name="John"
}

popeye 2021-02-16T14:59:02.221300Z

I want to replace whatever comes from where

popeye 2021-02-16T14:59:13.221700Z

how can i achieve in clojure

grazfather 2021-02-16T15:10:35.223700Z

fwiw, my first little project in clojure was because I was cold in my apartment. https://twitter.com/Grazfather/status/1361688395806879749

1
🔥 1
grazfather 2021-02-17T15:13:32.289900Z

Really simple: oz and an i2c library to read from the sensor.

grazfather 2021-02-17T15:13:41.290100Z

and just slurp to hit the API

oly 2021-02-16T15:15:43.223900Z

@noisesmith thanks for that info good to know that's possible I will give it a try 🙂

popeye 2021-02-16T15:16:56.224300Z

I would like to split

Select * from table
WHERE 
 {
    a.name="John"
}

popeye 2021-02-16T15:17:07.224700Z

as

Select * from table

popeye 2021-02-16T15:17:15.225Z

WHERE 
 {
    a.name="John"
}

popeye 2021-02-16T15:20:39.225500Z

anything other than (clojure.String/split stmt #"WHERE")

2021-02-16T15:21:05.225600Z

I've used this technique in production, making one jar with many namespaces with -main functions to invoke, it can simplify things when a bunch of processes will all use the same deps

2021-02-16T15:21:50.225800Z

(that is, not using anything outside the jar, but having multiple entry points in that jar that can be run - kind of like what busybox is for embedded *nix)

2021-02-16T15:23:05.227200Z

using string manipulation on SQL should be avoided, you can look at honeysql for example if you want to do generated queries

2021-02-16T15:23:30.228Z

this is the source of "sql injection attacks", one of the most expensive errors in the industry

👏 1
dpsutton 2021-02-16T15:23:32.228100Z

it really depends on whether your question is recognizing a pretty static template (anything inside of the { and } braces) or parsing arbitrary sql

2021-02-16T15:24:30.229200Z

for the latter, get an SQL parser, there must be multiple out there

2021-02-16T15:25:07.230400Z

but just because you parse most input correctly doesn't make any transformed result safe to run against data that matters

2021-02-16T15:26:06.231800Z

and regex operations are even worse

athomasoriginal 2021-02-16T15:42:53.231900Z

An anonymous function is both: (fn [a] (do-something a)) and #(do-something %) - is there a name to differentiate the two “syntax styles”? I’m tempted to say “literal anonymous” v. “anonymous”.

2021-02-16T15:44:17.232Z

The official Clojure docs call the #( ... ) syntax "anonymous function literal": https://clojure.org/reference/reader#_dispatch

2021-02-16T15:45:05.232200Z

I do not know of any special distinguishing name for a (fn [ ... ] ...) expression.

athomasoriginal 2021-02-16T15:46:11.232400Z

indeed.

2021-02-16T15:47:16.232600Z

one is a standard invocation (of a macro), the other is a reader macro expanding to the same special form

2021-02-16T15:47:41.232800Z

(ins)user=> (macroexpand '(fn []))
(fn* ([]))
(ins)user=> '#()
(fn* [] ())

2021-02-16T15:48:08.233Z

the extra () is a side effect of how that reader macro works

athomasoriginal 2021-02-16T15:51:04.233200Z

Nice and I’m thinking about new developers where for their benefit, it’s helpful to have a name to associate to a “style” to aid in their learning journey.

Mno 2021-02-16T15:53:30.233400Z

That’s amazing honestly

Mno 2021-02-16T15:55:09.233600Z

I generally refer to it as the “anonymous function shorthand” as verbose as that may be 😅

athomasoriginal 2021-02-16T16:38:14.233800Z

fair enough and makes sense!

oly 2021-02-16T16:44:58.234Z

good to know I just wanted a quick way of running a maintenance task running in a pod so this should work nicely.

2021-02-16T17:06:08.234400Z

can clojure do that? woww....

rafalw 2021-02-16T17:14:35.235300Z

Hi, I have such use case. I have map which is single point of truth, and I have module with functions which operates on this map, something like this:

(defn get-something [db ...] ...)
(defn update-something [db ...] ...)
...
And I have two use cases, first simple where, app is single threaded, second where app is mutlithtreaded and db is an atom. For multithreaded version I've created new module and wrapped every function from the first module in 'swap!', deref etc. for example
(defn update-something  [db ...] (swap! db a/update-something ...))
...
The issue is that, every time I add something to the first module, I have to write 'wrapper' in second module. Is there a way to avoid this duplication, and for example dynamically discover which version to use? Would multimethods be good fit here?

mruzekw 2021-02-16T17:17:58.236Z

Atoms are useful and useable in a single threaded environment. Could you use an atom for both cases?

rafalw 2021-02-16T17:21:19.239Z

I could, I'm just wondering if is there some 'elegant' solution, because in single threaded version using atom sounds like wasting cpu cycles (maybe I'm wrong about this....)

mruzekw 2021-02-16T17:23:23.240500Z

I don't think there's much to worry about perf wise. If it becomes a problem, you can always switch it out later. For me, I'd see using an atom in both cases as an elegant solution.

2021-02-16T17:23:26.240700Z

In single-threaded environment unless you are doing these swap! calls millions of times per second, I doubt you'll notice a performance difference using it in a single-threaded program.

👍 1
2021-02-16T17:27:08.240800Z

In a single-threaded program, the overhead of swap! should be no more than one Clojure function call (the update function you pass to swap!), a pointer-equality check, and a JVM compare-and-swap operation that should be optimized to a single CPU instruction if it is in a hot code path.

💯 1
mruzekw 2021-02-16T17:28:12.242Z

Is there a way to grab the metadata of a passed in value?

(defn get-fragments [comp]
  (get-in (meta comp) [:helix/opts :apollo-cljs/fragments]))

mruzekw 2021-02-16T17:29:03.243700Z

All the examples I see show use of the exact symbol plus a reader macro

(meta #'Username)

mruzekw 2021-02-16T17:31:54.245600Z

Right now I'm trying to use the fn as (get-fragments Username) But I just realized maybe passing in #'Username would work instead. Doable, but not my ideal

Illia Danko 2021-02-16T17:33:33.246800Z

Hello folks. I have a nested 3 lvl data, such as [[[1 2] [3 4]] [[5 6] [7 8]]] . And I want to extract it to lvl 1 to become (1 2 3 4 5 6 7 8). I came up with

(->> [[[1 2] [3 4]] [[5 6] [7 8]]]
          (apply concat)
          (apply concat))
But what if the nesting will be more than 3 lvl in depth? And I don't like repeating my self with (apply concat) . Is there more functional (contrived :)) approach to tackling the issue?

tvirolai 2021-02-16T17:38:05.247300Z

You could use flatten

👍 2
Illia Danko 2021-02-17T09:38:51.277800Z

@qmstuart good to know, anyway flatten fits well with my issue

Illia Danko 2021-02-16T17:40:18.247500Z

that exactly what I need, thank you

2021-02-16T17:41:23.247900Z

If Username is a var that has whatever value you want to pass in to the function get-fragments, calling (get-fragments Username) passes the value of Username, but not the Var object itself.

2021-02-16T17:42:22.248100Z

Clojure collections can have metadata 'attached' to them, and if Username had a value that was say, a map, and that map had metadata attached to it, then calling (get-fragments Username) would cause the (meta comp) call inside of get-username to get the metadata attached to that map.

2021-02-16T17:43:42.248600Z

If the metadata you want is on the var #'Username, you can call (get-fragments #'Username) to pass the var to get-fragments, and then the (meta comp) call will get the metadata on the Var, if any.

mruzekw 2021-02-16T17:44:49.248800Z

Okay thanks! Yes. Username is var (symbol made from a macro)

2021-02-16T18:30:07.249200Z

flatten might work if you only have vector of vectors, lists etc but for example if you have something like a set:

(let [xs [[1 2] [3 4] [5 6] [7 #{8 9 19}]]]
    (flatten xs))

=> (1 2 3 4 5 6 7 #{19 9 8})
It won't work. AIUI, It will go into subitems if they return true for sequential? So just be aware of this.

2021-02-16T18:39:42.249400Z

atoms / swap! are indeed slow, you can use volatile! and vswap! in a single thread, or better yet use values as much as possible instead of holding and maintaining state. depending on app design / usage you could use an agent (guarentees that changes are serial but send returns before the change is applied) and/or some sort of queue consumer / data reducing pattern if the update patterns fit that

2021-02-16T18:53:10.249600Z

IMHO a data domain which treats multiple levels of nesting as equivalent to the flattened form is usually a design error, but flatten does do the specific thing you ask for

2021-02-16T18:53:57.249800Z

it's often a brittle element though, because we often want to refactor code that took an item to instead take collection types and flatten makes that break

Zak Singh 2021-02-16T20:02:12.257100Z

Hi all, I’m having a bit of confusion regarding futures. I’m calling a process in the shell from my Clojure code and using a future to keep track of the streamed output. Here’s the code:

(defn start-server []
  (sh/proc "/bin/sh" "-c" "c8 node index.js"))

(defn stop-server [process]
  (let [output (future (sh/stream-to-string process :out))]
    (sh/destroy process)
    output))
When I run this, output has an error “Stream closed”. However, when I run these commands one by one in the REPL like so:
(def s (start-server))
(def o (future (sh/stream-to-string s :out)))
(sh/destroy s)
Then print out o, I correctly get the terminal output of the program between when I started and destroyed it. Is there something about using “let” in the first example which makes the future not evaluate until after the sh/destroy call has been made? “Stream closed” should only occur if I try to call stream-to-string after destroying the process, but I can’t see why that would be happening here

2021-02-16T20:06:00.258Z

A future is a separate thread, evaluation happens in parallel

2021-02-16T20:07:46.260500Z

Once the new new threading is running there is no defined ordering relationship between what is being executed in your two threads, so what you have is a race condition

Zak Singh 2021-02-16T20:11:14.260600Z

So in other words the sh/stream-to-string call might actually occur after the sh/destroy call on the other thread… makes sense. Is there a better way to go about what I’m trying to do? (run a program, store its output as its running, then kill it)

Zak Singh 2021-02-16T20:12:00.260800Z

or at a smaller scale - enforce ordering here?

2021-02-16T20:15:17.261Z

I guess the question is, why are you calling stream-to-string in a different thread from destroy, if you want destroy to be called after stream-to-string

2021-02-16T20:16:36.261200Z

There are ways to do that, but the simplest thing is to put them both on the same thread, and the simplest way to do that is to stop using future

Zak Singh 2021-02-16T20:20:00.261400Z

I used the future because stream-to-string seems to block indefinitely since it’s waiting for the process to end (which it doesn’t since I have to kill it manually using destroy)

Zak Singh 2021-02-16T20:21:27.261700Z

so from my understanding I need to run it on a separate thread so that I’m able to call destroy when I need to

2021-02-16T20:26:34.261900Z

So how do you know when you need to call destroy?

Zak Singh 2021-02-16T20:28:58.262100Z

I’m writing a tool to fuzz a nodejs API, so it starts the API using c8 (which prints code coverage metrics to the terminal), runs a bunch of commands against the API, then shuts it off and inspects the output to view code coverage metrics. So it would be programmatic (but hard to illustrate here)

Zak Singh 2021-02-16T20:30:57.262300Z

in reality this may not be a problem since the time between calling stream-to-string and destroy will be at least a few minutes, so the chance of a race condition would be virtually impossible

2021-02-16T20:31:07.262500Z

So put (when X (destroy ...))

2021-02-16T20:31:27.262700Z

The figure out X

Zak Singh 2021-02-16T20:32:22.262900Z

alright perfect - thanks for the help. Sorry for the silly question, talking it out really helped clear things up