This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-01-24
Channels
- # aleph (13)
- # announcements (3)
- # beginners (134)
- # calva (9)
- # clojure (33)
- # clojure-europe (19)
- # clojure-nl (2)
- # clojure-norway (42)
- # clojure-uk (7)
- # clojurescript (43)
- # core-async (7)
- # core-typed (2)
- # cursive (32)
- # datomic (19)
- # fulcro (5)
- # gratitude (4)
- # hyperfiddle (26)
- # introduce-yourself (1)
- # jobs-discuss (15)
- # lsp (3)
- # malli (20)
- # off-topic (18)
- # overtone (3)
- # polylith (24)
- # squint (22)
- # xtdb (21)
I would like to do something like read-from-file-with-trusted-content
from https://clojuredocs.org/clojure.core/read but I'd like to do it effectively from a shell script or makefile. I've processed a correct clojure file and i've elided some expressions which my students are supposed to replace with correct code.
I want to check to make sure that my eliding script has not mis-matched the parentheses, brackets, braces, etc.
Currently I'm using lein check
but that doesn't work, as lein check
checks too many semantics for my need, I just want to check read syntax, not compile integrity.
An example of elided code might be the following
(defn hyphenated-names
[base-name]
(assert (= base-name (lower-case base-name))
(cl-format false "hyphenated-names must be called with lower case name, not [~A]" base-name))
(let [s (io/resource "France-baby-names/nat2020.csv")]
(with-open [r (io/reader s)]
(set (for
;; CHALLENGE: student must complete the implementation.
(throw (ex-info "Missing one or more expressions, not yet implemented" {}))
)
)
)))
lein check
complains that the for
syntax is wrong
if you can clojure.edn/read
it, then it's got correctly balanced brackets, and well formed symbols, etc ... is that good enough?
if i'm not mistaken, read
both the one in clojure.edn
and also clojure.core
only read the first sexpression in the stream. right?
so I think I need to loop and read until EOF.
but I don't understand the difference between those to variants of read
you can repeatedly read from a reader until the end of the file with something like
(import '[java.io PushbackReader])
(require '[clojure.java.io :as io] '[clojure.edn :as edn])
(with-open [rdr (PushbackReader. (io/reader (io/file (str system-file))))]
(loop [els []]
(let [el (edn/read {:eof ::eof}
rdr)]
(if (= el ::eof)
els
(recur (conj els el))))))
Actually won't that fail if there is a line containing ::eof in the file?
I'm using something like this:
(defn line-read-file
"Read all the lines from a file and return an vector of lines which have been read"
[filename]
(println [:open filename])
(with-open [r (java.io.PushbackReader.
(clojure.java.io/reader filename))]
(binding [*read-eval* false]
(let [eof-value (list :end)]
(loop [lines []
line (read r false eof-value)]
(if (identical? line eof-value)
(printf "read %d lines from %s\n" (count lines) filename)
(recur (conj lines line)
(read r false eof-value))))))))
::eof
is namespaced to the code that you're reading the file in ... so it seems unlikely that it'll be in the code your reading?
it is impossible for read
to return a list identical?
to a list I've allocated at run-time.
the way read
works in CL seems to be the same conceptually as in clojure. you give read
a special value and it returns exactly that value if it encounters end of file, then you can test using pointer equality whether it returned exactly that value.
I don't think it's easy to return a value that's identical?
to something already in ram from read
, unless it's a keyword
that is the point. read
returns exactly its 4th argument when it reaches end of file, as long as the third argument is false
. it seems to me the correct way to detect end of file is to test whether read
returned that exact value as documented.
am I wrong?
ah yeah ... sorry - I misunderstood what you meant ... yes, when it gets to the end of the file thing you give it
anyway, i can replace clojure.core/read
with clojure.end/read
, no problem to avoid run-time evaluation
but I suspect *read-eval*
controls the same thing.
BTW, I don't understand what `
(java.io.PushbackReader.
( filename))
does. I call ls
in the shell before calling the clojure script, and I verify that the file is there. however, when I run the script it seems that
is unable to find it.
clojure.lang.Var.applyTo (Var.java:705)
clojure.main.main (main.java:40)
Caused by: java.io.FileNotFoundException: binarysearch.clj (No such file or directory)
at java.io.FileInputStream.open0 (FileInputStream.java:-2)
java.io.FileInputStream.open (FileInputStream.java:219)
i'm calling the script using lein exec
. is that changing my CWD?
edn/read
supports a subset of clojure while *read-eval*
disables some features of the clojure reader
yes, lein exec
changes the directory. I print the value of (-> (
inside the script, and it is different than the directory lein exec
is called from.
oops ... tell a lie ... it does this
(try
(make-input-stream (URL. x) opts)
(catch MalformedURLException e
(make-input-stream (File. x) opts)))
I took the code from here https://clojuredocs.org/clojure.core/read
is that wrong?
nope ... it's me that's wrong - if you pass io/reader
a string it will try and turn it into a url and if it's invalid it'll assume it's a file and try to read that - you problem is probably that you've got a relative path and you're in the wrong dir
my string is exactly the string "binarysearch.clj" and I've verified it is in the directory I started lein
in. But within the program I print the directory and it is no longer the same directory.
perhaps lein tries to walk up the directory to the top of the project???
it is surprising, but i can call my script with full path names to avoid this annoyance.
seems it does that. changes directory to where it finds the project.clj
file
I didn't bother reading the documentation of lein exec
. it is probably documented behavior.
what is the clojure equivalent of the common lisp (and all other lisps) eq
?
via interop:
(let [x (Object.)]
(.equals x x))
;; => true
(.equals (Object.) (Object.))
;; => false
why not use identical?
ha) I never use it because clojure's equivalent semantic is good enough for all my cases. IMHO, equivalency check makes sense only if you do heavy interop to java. That is why I never bothered to look for identical?
function.
as I understand it is the only way to dependably use the 4th argument of read
read
returns its 4th argument exactly when trying to read past end of file. to detect this you must use identical?
to distinguish the improbable case that it read something =
to your 4th argument
at least that how it works in common lisp and it looks like clojure read
was modeled off that.
(let [t (random-uuid)]
(loop [acc [] rdr rdr]
(let [x (read {:eof t} rdr)]
(if (= x t)
acc
(recur (conj acc x) rdr)))))
You don't have to use identical?
and btw, you have to have really strong argument to use read
. IMHO, it is always a mistake. Use clojure.edn/read
insteadmy sense was if I'm reading edn data I should use end/read
and if i'm reading clojure code I should use normal read
but just make sure *read-eval*
is bound to false.
what is the reasoning I'm missing?
what is random-uuid
?
it seems like you're just making it very unlikely to read t
from the file. it seems better to me to depend on the documented behavior of read
and just detect whether it returned the think I said to return on eof.
no need to generate a randomized uuid
BTW, my original question was also intended to ask whether there is already a function which will slurp in the entire file, or whether the programmer is required to explicitly call read
(or cousin) repeatedly
read this https://clojuredocs.org/clojure.core/read#example-542692d5c026201cdc327056
> what is random-uuid
?
function to generate a random UUID. it doesn't matter what function to use here. In most place where I have to use clojure.edn/read
I simply use ::eof
as a token. And yes, it might not consume input completely when by some reason there is a single top-level token matching :some.namespace/eof
.
> it seems better to me to depend on the documented behavior of read
What makes you think I'm suggesting you something different?
because if you use any token for the eof marker, if read
reads that object at the top level, read
will return in and your equivalence check will match and the read
loop will terminate before the file is completely exhausted. it seems to me the only way to detect eof is to detect whether read
returned exactly and identically your given eof marker, and to distinguish that from the case when read
returned something different but not identical to that eof marker.
wrt the clojure doc, I did read that. it advises that you should not read untrusted data with read
. that's not my case. I'm reading data which I just created. However, if there's some other reason than trust, perhaps I didn't really understand what I read.
Then why you read data you just created?
You can use a freshly created Java Object
instance as the sentinel value that read
returns if it gets an error, and then use identical?
between that freshly created object and the return value. I don't know any other shorter way to guarantee whether the return value is from the file vs. not.
I believe for a freshly created Object
instance like that, that Clojure =
will be handled by reference equality, too.
> Then why you read data you just created?
because I didn't create it in the same process. I created in this case from a python program.
I want to point my :expr-deps in my :aliases to a directory where there are many .jar files which are my dependencies. From how I understand this, I can add a directory and must not specify all the jars one by one (see screenshot) I use something like this (screenshot2) but it gives me:
Error building classpath. Local lib lib/libs not found: /obox/wwww/WEB-INF/lib
:local/root
must be either a path to jar or path to clojure project with manifest (e.g. deps.edn).
you can also write a small babashka script to prepopulate your project's deps.edn based on a content of some folder )
This is a total hack but Java accepts limited form of wildcarding so it probably works to add “dir/*” to your :paths or :extra-paths. Haven’t tried it
Guys I am really struggeling. I have org.babashka/http-client {:mvn/version "0.4.15"}
in deps.edn and in my (ns my-ns (:require [babashka.http-client :as http]))
but I get :
; Syntax error compiling at (babashka/http_client/interceptors.clj:1:1).
; namespace 'babashka.http-client.internal.multipart' not found
I asked some months ago whether anyone was interested in volunteering to be a guinea pig for some/all of my student exercises for a course I'm developing. I've lost the thread.
off-topic, please use threads for multiple messages. It is asked in channel's description
thanks for the reminder
@U010VP3UY9X I've deleted several of your top-level channel messages from this morning. In future, please stay on topic for the channel and use threads -- we have plenty of other channels where some of that would have been on-topic /admin
is anyone interested in looking at some of these exercises and giving me feedback?
i'm doing a last pass through the homework problems fixing all the docstrings I see as being problematic
i'm surprised to see that although map
takes an n-ary function an n-many sequences to map across in parallel, every?
unfortunately does not.
or perhaps it does but is not documented as such.
something like the following ought to work
(every? == '(1 2 3) '(1.0 2.0 3.0))
and what if
(every? == '(1 2 3) '(1.0 2.0 3.0 4.0))
are you asking how should it be implemented? I'd say do it like common lisp does it. but i understand that someone else might say not to use CL as the standard.
No, I'm asking about what you expect
in CL it is documented that if the 2nd list (or nth) list is longer than the first, the extra values are ignored. but if the first argument is longer than any subsequent, then a run-time error is signaled
isn't that what map
does?
I guess I'd like it to be consistent with map
@U0P0TMEFJ just an example. actually what I wanted was (every? (almost-equal 0.0001) '(1 2 3) '(1.0 2.000000000001 3.0) )
good to know about map
.
but anyway, every?
implies it should eagerly check everything. That is why I'm asking what do you expect in a situation when there are uneven length sequences
no, i'd expect it to work by the same traversal rules as map
@U0P0TMEFJ that's ugly, but not your fault. could also do some sort of take-until-false
or take-until-true
concoction with (map == list-1 list-2)
(defn my-every? [pred & args]
(if (= 1 (count args))
(every? pred (first args))
(every? #(apply pred %) (apply map list args))))
(my-every? == '(1 2 3) '(1.0 2.0 3.0))
;; => true
(my-every? == '(1 2 3) '(1.0 2.0001 3.0))
;; => false
there's some function like some
which asks whether something in the list is false.
I always mix up the functions like some
vs some?
etc
Hi, how in clojure make sorted subset of sorted set ? In java I can do next
jshell> new TreeSet<>(Arrays.asList(2,3,4,5,6)).headSet(3, true)
$13 ==> [2, 3]
Result is again SortedSet. So I can continue to work with result as with sorted set
jshell> new TreeSet<>(Arrays.asList(2,3,4,5,6)).headSet(3, true).headSet(2,true)
$14 ==> [2]
In clojure I found next way
user> (apply sorted-set (subseq (sorted-set 2 3 4 5 6) <= 3))
#{2 3}
Does exists more simple way to create subset of sorted set?(into (sorted-set) (subseq #{,,,} <= 3))
or clojure.set/select
(type #{1 2 3})
;; => clojure.lang.PersistentHashSet
(type (sorted-set 1 2 3))
;; => clojure.lang.PersistentTreeSet
(type
(clojure.set/select #(<= % 3) (sorted-set 1 2 3)))
;; => clojure.lang.PersistentTreeSet
@U04V4KLKC Did you mean to use subseq
instead of subset
in your code snippet above?
@U0CMVHBL2 yes, thanks
i think those proposals are linear whereas the ask is for a less-than-linear approach
It should be linear in the size of the subset, not the full set you are taking the subset of, but if that is what is desired, I am not aware of anything built into Clojure that would achieve faster-than-linear subset creation like that.
🤷 the question was about returned type not performance
(and to be precise, when I say "linear" here it is really more like O(N log N) than it is O(N))
clojure.data.avl has a sorted set with some nice properties
"An implementation of persistent sorted maps and sets based on AVL
trees which can be used as drop-in replacements for Clojure's
built-in sorted maps and sets based on red-black trees. Apart from
the standard sorted collection API, the provided map and set types
support the transients API and several additional logarithmic time
operations: rank queries via clojure.core/nth (select element by
rank) and clojure.data.avl/rank-of (discover rank of element),
\"nearest key\" lookups via clojure.data.avl/nearest, splits by key
and index via clojure.data.avl/split-key and
clojure.data.avl/split-at, respectively, and subsets/submaps using
clojure.data.avl/subrange."
❯ clj -Sdeps '{:deps {org.clojure/data.avl {:mvn/version "RELEASE"}}}'
Downloading: org/clojure/data.avl/maven-metadata.xml from central
Clojure 1.11.1
user=> (require '[clojure.data.avl :as avl])
nil
user=> (avl/subrange (avl/sorted-set 0 1 2 3 4 5) > 1)
#{2 3 4 5}
Thanks for all answers!
Lets say that I have the following
;;core.clj
(ns tree-prun-api.core
(:require [tree-prun-api.infra.repository :as r :refer [->GisRepository]])
(:gen-class))
;;here a a instance of a type from tree-prun-api.infra.repository, that uses scripts, is called
...
;;repository.clj
(ns tree-prun-api.infra.repository
(:require [tree-prun-api.domain :as d :refer [AGisRepository
DataResponse
make-entity
->GeoCoordinate]]
[tree-prun-api.infra.scripts :refer [scripts]]
[clojure.java.jdbc :refer [query execute!]])
(:gen-class))
;;here scripts from tree-prun-api.infra.scripts is called
...
;;scripts.clj
ns tree-prun-api.infra.scripts
(:require [clojure.string])
(:gen-class))
(defn getScript
([typeName]
[typeName
(slurp
(clojure.string/replace
*file*
#"scripts.clj"
(str "scripts/" (name typeName) ".sql")))]))
(def scriptBinds
[:getPoles
:getPolesFilterCoords
:getFeederCircuits
:getPowerTranformers
:getPowerTranformers
:getSwitches
:getTowers
:getWires
:insertPole])
(def scripts
(reduce
#(try
(conj % (getScript %2))
(catch Exception e
(println ";" (.getMessage e))
%))
{} scriptBinds))
I'm using lein to run. When I use it inside ns tree-prun-api.infra.scripts, file works ok. And if i run things there all good. But if I need to start the project on ns tree-prun-api.core, that require tree-prun-api.infra.repository, and inside repository require tree-prun-api.infra.scripts, seems not to work.
Is there any way to that file (any other methot to replace file here) be relative scripts.js location (tree-prun-api.infra.scripts)?
Image here showing data file structure,I'm trying to read scripts folder that are on same folder "infra" where is scripts.clj , so I can read each script. (relative to it)
*file*
is bound at compile time when the compiler loads a file, outside of that context the value it has is undefined
the way this is kind of thing is usually done is using what are called "resources" which are things that are not class files that can be loaded from classloaders
http://clojure.java.io/resource is a convenient way to get a handle on a resource
most build tools(like lein) follow the convention of putting resources in a distinct folder usually "resources/"
Got it, thanks. I shall move the files to there right now
I wanted to leave inside infra, because is part of it haha. But i'll move them to there right now
got it, thanks!
a separate resources/ folder is something build tools do just so people can feel more organized
Hi All (moved this from the clojure channel to here), Been lurking for a while now, was curious if anyone has used this with Kafka, if it's even possible? I'm looking to change up the way I do CEP and have gotten more into Clojure and thought this would be neat to play around with. https://github.com/PyroclastIO/metamorphic/tree/master
I have not used metamorphic, but if I understand correctly, Jackdaw might be something you could use https://github.com/FundingCircle/jackdaw
Thanks! I'll check this out