or you could use that generator to unpredictably shuffle a vector/array of integers mapping to the range AA000 to ZZ999, as you had in mind. they're fewer than a million, so keeping them in memory is doable
trying to build an uberjar with depstar - I'm getting
clojure -X:depstar uberjar :jar MyProject.jar
2021-01-02 20:48:09.772:INFO::main: Logging initialized @2905ms to org.eclipse.jetty.util.log.StdErrLog
Execution error (FileNotFoundException) at java.io.FileInputStream/open0 (FileInputStream.java:-2).
-X:depstar (No such file or directory)
seems like i needed to update clojure
when building an uberjar, is the app supposed to be executed? the guide [here](https://github.com/seancorfield/depstar#basic-usage) suggests using :replace-deps
, but when I try and build the uberjar, it fails, and the error messages suggest that some dependencies are missing
Yes, the -X option is a recent addition to Clojure CLI
Did you add the depstar
alias in your config file? in which one? Please copy it here so we can help.
In case it helps, here is a usage of the previous version: https://github.com/green-coder/girouette/blob/master/deps.edn#L11-L22
I see 🙂
:aliases {:uberjar
{:replace-deps {seancorfield/depstar {:mvn/version "2.0.165"}}
:replace-paths ["src/clj"]
:exec-fn hf.depstar/uberjar
:exec-args {:jar "MyProject.jar"
:aot true
:main-class project.core}}}
here, you should use the alias uberjar
instead of depstar
because that’s how you named it.
oh?? isn't the alias just a name?
let me try that again
thanks! with that config, I did clojure -X:uberjar
and I'm getting an error finding mount
, but mount is in my dev/
directory - did i use :replace-paths
correctly?
I never used :replace-paths
and did not find its documentation on depstar’s page.
using collections as values does have a hidden cost. While the hash values are cached, at the end of getting from a map there is a comparison between the found key and the provided one (as they might) have the same hash. Comparing collections is very expensive in relation to getting a value from a map
This is where it happens:
public Object find(int shift, int hash, Object key, Object notFound){
int bit = bitpos(hash, shift);
if((bitmap & bit) == 0)
return notFound;
int idx = index(bit);
Object keyOrNull = array[2*idx];
Object valOrNode = array[2*idx+1];
if(keyOrNull == null)
return ((INode) valOrNode).find(shift + 5, hash, key, notFound);
if(Util.equiv(key, keyOrNull))
return valOrNode;
return notFound;
}
@ackerleytng As the depstar
README says: Note: these instructions assume you have at least version 1.10.1.727 of the Clojure CLI installed
clj-new
is the same: requires at least 1.10.1.727
oh thanks! missed that
https://clojure.org/reference/deps_and_cli#_replace_project_environment_tool <= I thought :replace-paths
was a cli/deps.edn thing
@ackerleytng If your app depends on things that you would need to provide aliases for, you need to tell depstar
what those aliases are.
> when building an uberjar, is the app supposed to be executed? perhaps unrelated to your error, but a very common misunderstanding is that clojure doesn't have a "compile mode" - if your def has a side effect, it will run while compiling the file
See this section of the README:
As of depstar 2.0, the classpath is computed from the system and project deps.edn files. If :repro false, the user deps.edn file is also used. This is intended to correspond to the CLI's -Srepro option that ignores the user deps.edn file. If you need to adjust that classpath, based on aliases, you can supply a vector of aliases to the :aliases exec argument of depstar.
I suspect you have an alias (maybe :dev
?) that adds dev/
, you need to specify :aliases [:dev]
(or whatever that alias is).
I added dev/
to :paths
in the deps.edn
and i was going to :replace-paths
when building the uberjar
do you recommend removing dev
from :paths
and then adding it using an alias for dev purposes?
If something needs to be in your final app, it probably shouldn't be under a separate alias -- it should be in your core :paths
value (and you wouldn't use :replace-paths
).
i only need the stuff in the dev/
directory for dev, so it shouldn't be in the final app
(it's very rare that you would ever need :replace-paths
)
including dev in an uberjar just sounds weird to me
Agreed. But it sounds like you have stuff in your main code that refers to things that are in your dev
folder -- which doesn't sound right @ackerleytng
this is a great point, but also note that the collection equality check is cheap if the key used for lookup and the key in the map are the same object in memory
> I'm getting an error finding mount , but mount is in my dev/
directory
can you explain what you mean in this sentence?
what does finding mount mean?
I think it could be because i originally put dev/
in :paths
, which puts it in the final app.
mount is this dependency https://github.com/tolitius/mount
sure. what does "finding mount" mean?
and how is mount in your dev/
directory
oh wait mount is a dependency in my ~/.clojure/deps.edn
and [mount.core :as mount :refer [defstate]
referenced in dev/user.clj
that's a bit strange. if you depend on mount, add it as a dependency. seems strange to have that only in dev and not throughout the app. not sure what its purpose is there
Hi everyone and I wish a happy new year to all 🙂 I've been working through the book Living Clojure but I'm now stuck on the chapter where we mix cljs code with clj code - I can't get the cljs repl to run - I enter the line the book tells me lein trampoline cljsbuild repl-rhino
on the Windows commandline and it tells me Syntax error (FileNotFoundException) compiling at (cljsbuild\repl\rhino.clj:1:1).
Could not locate cljs/repl/rhino__init.class, cljs/repl/rhino.clj or cljs/repl/rhino.cljc on classpath.
Any ideas what I might be doing wrong?
in my app, i start jetty from main directly
Well, if your uberjar is failing because it's looking for mount then, yup, it should be a core dependency in the project. I can't imagine how you'd build an app that only uses mount at dev time -- it's kind of intrusive with its global state (which is why I won't use it).
but i use mount for development so i can stop jetty and restart it
If you really think you're only using mount at development time then you absolutely do not need to use mount at all.
but if mount isn't sprinkled throughout the app, aren't you just calling a single start and stop on the server? if its not really dealing with dependencies its just an alias for the start and stop of the server
You can easily stop/start jetty directly.
i think the rhino repl was removed from clojurescript recently (ish). That's a pretty old style to get up and running
one possibility is that it should work if you use the version of clojurescript that's in use in the book
i see a repo from the author working through one of the examples at https://github.com/gigasquid/cheshire-cat which specifies a clojurescript version [org.clojure/clojurescript "0.0-2371"]
ohh i see. would it be like (def server (run-jetty ...))
and then if i need to stop it, do (.stop server)
?
from github i see that was released on october 9, 2014 and is so old that all of the tooling around it is very out of date. the tutorial itself might still be valid but i haven't seen it. the author's very interesting and done some of my favorite exploratory and fun coding (chemical computing: https://gigasquidsoftware.com/chemical-computing/index.html)
yeah. i'm guessing that's what you have in your dev namespace right?
(defstate ...)
I didn't think Living Clojure was that old, but I've sort of lost track of when various books were released at this point...?
April 2015. Wow. Almost six years ago!
Given my recent experience, coming back to cljs after last looking at it in 2014, things have really changed in the cljs world...
yup that's what i have!
thanks i'll remove mount
Remove mount completely from your memory 🙂
🙂
Ah OK thanks dpsutton, sean, might try specifying the same clojurescript version as is in the book then so hopefully that should work or I will need to figure out how to do it the modern way
I didn't know how to get started with a ring server and mixed clj/cljs with deps.edn so just followed along with the book's Leiningen instructions also, would be nice to know how to do it with deps.edn if there is anything easy I can look at?
i'd check out figwheel main's documentation and look for a template with it built in
OK thanks, I'll have a look at that 😉
@flyingpython I am just getting started with ClojureScript (it's all so different to when I last looked at it that I'm a beginner all over again), and I'm liking Figwheel Main, and as you know I'm using deps.edn
. I don't have a combined front + back end app together yet but I'm working on getting something basic together that I'll probably use as a model for what I need to build at work...
I'll put it up in a public repo when I have something working end-to-end.
(and of course I'm making this all work with Reveal and Atom/Clover)
OK that sounds promising Sean, not sure if I'll be able to understand it though?
Happy to talk you through it, once I get it all up and running 🙂
OK thank you very much, I will look forward to having a look at it 😉
At this point in the book I just need something equivalent to lein ring server and getting a ClojureScript REPL up and running (especially if I can do this with Clover/Chlorine) I've been using Chlorine and deps.edn config throughout the book until I got to this chapter as I was unsure how to translate it from Leiningen to deps.edn and socket REPL setup
@flyingpython Figwheel is pretty easy to use with deps.edn
and the Clojure CLI.
I used a figwheel-main-template
, told it I wanted a --reagent
app. Then clojure -M:fig:build
and I was up and running.
:thumbsup: That's great; I like easy!
(then I added re-frame
and converted it from Reagent to re-frame; next I plan to add an http lib so I can call from the front end to the back end I'll build)
It is on GitHub but I haven't updated the readme at all so it's not accurate. I'm still poking at tooling and figuring out how best to work with this new-to-me ecosystem 🙂
I have updated my dot-clojure files to work with figwheel and reveal tho'... (and I updated that readme to cover some of this)
OK, sounds cool, just drop a line on the Chlorine channel or something like that when you have it updated and I'll have a look though I'll probably look soon anyway for lack of patience 😃
would people recommending having a single deps.edn for both frontend and backend?
i don't think there's a mechanism to have two. so yes
how should i set up paths? the paths are mostly different, right?
Hmm, I've seen projects with more than one deps.edn in them though - maybe the other deps file was just an old artifact they weren't using anymore though if it is indeed the case you can't use more than one
you could do src/frontend
and src/backend
. leads to some awkward bits when you have shared code
@flyingpython if they had more than one deps.edn, what were the filenames?
oh i meant :paths
in deps.edn
figwheel seems to be expecting paths defined in :paths
, which means when i build the uberjar i have to override paths...? does that sound right?
there should be no trace of figwheel in the uberjar - figwheel is a dev time tool and in your final artifact you should just have the javascript that cljsbuild outputs
yup! my deps.edn file has both frontend and backend stuff in it. i think i figured it out, here's my final deps.edn https://github.com/ackerleytng/gowherene/blob/master/deps.edn
I can't remember the filenames as it was in the past I saw it, they were in different folders in the project though, I assume the filenames were both deps.edn as I am pretty sure that is what I saw but could be wrong given the fallibility of human memory and all
@flyingpython this is a nice & relevant book about clj / cljs integration (lein, shadow-cljs, raegent and re-frame,..). Still in beta though. https://pragprog.com/titles/dswdcloj3/web-development-with-clojure-third-edition/
ah. yeah i've seen that. and a top level one that uses the sub projects with :local/root
. an example is chui: https://github.com/lambdaisland/chui
Figwheel should only care what is on the classpath when you run it -- which you can control with aliases.
OK thanks for the recommendation, I would prefer one with deps.edn though as that is what I've mostly been what I've been using though and I prefer it once I got started, Leiningen is easier to jump in and start with, but I find with deps.edn it seems less magical to me as to what is going on
It's certainly reasonable to have :client
and :server
aliases that specify different paths (and you can still have shared code -- specified in both aliases' :replace-paths
or :extra-paths
(I'd probably use the latter and have the main :paths
just be the shared code).
And when you build the (backend) uberjar, just tell depstar
to use :aliases '[:server]'
And for the front end: clojure -M:client:fig:build
should work for development (and clojure -M:client:fig:min
for a "prod" build, if I'm reading the figwheel template right).
And then a separate REPL to run the server: clj -M:server -r
(plus whatever other aliases you want).
(for me, the only quirk would that my dev tooling assumes it can write a single .socket-repl-port
file into the project, so I would probably spin up both the client and the server together via figwheel and my :dev/repl
alias while developing)
(something like clojure -M:client:server:reveal:test:fig:build:dev/repl
I think, maybe with :add-libs
as well depending on whether I thought I might want to add new dependencies after starting my REPL)
goodness that's quite an incantation 🙂
Easy enough to hide via a shell script or a bash alias 🙂
I think my main REPL startup command at work has even more aliases in it. At least they compose nicely 🙂
True, for every other case, however, I have seen a sharp drop off in performance when hashing collections, making it a non-starter for anything which requires speed or high throughput =\ A plausible middle ground is creating synthetic keys via different methods, either string concatenation or keyword generation
@dpsutton OK yeah, I think like that lamdaisland example but I see there's a simple example on the https://clojure.org/guides/deps_and_cli page under "Using local libraries" they include part of their program as a library which has it's own deps.edn so I am thinking you can use as many deps.edns as you like so long as the source code and deps files are in their own separate folders
OK, I'm out for the night. I'll try to carve out some time tomorrow to add a server component to my little re-frame repo and write up the readme so it's all up-to-date.
yeah. its quite readable. and for sure a little alias or shell script would fix it
OK good night Sean, thanks for the help 😉
(now that I've incorporated a lot of the individual pieces into :dev/repl
and it adapts to whatever is on your classpath, my dev setup is a lot easier!)
Oh that sounds great!
i do wish cider worked with socket repls. alas
Once they have side-loading, that should be easy to do.
Chlorine/Clover side-load unrepl over a socket REPL (and Christophe was working with Bug on doing something similar with nREPL I believe).
Anyways. Bed.
FWIW, nREPL already has a sideloader, but it can’t inject itself over a socket REPL yet. Here’s the GitHub issue for it: https://github.com/nrepl/nrepl/issues/96
hi guys, I don't know where to ask. I'm working with toolnamespace/refresh function. It seems to be broken, no file modification is detected anymore. Don't know what to do, where to look. I remove main from my profile, as some advise.
Just in case, I restart my repl, started with a fresh copy of my repo....
I did not understand all the subtlety, but it appears my refactor-nrepl / cider-nrepl and tools.namespace were conflicting.
It works now I am using a cider-jackin as recommended https://github.com/clojure-emacs/refactor-nrepl#with-cider-and-clj-refactor
hi, how can I retrieve vectors instead of lists when using partition
? Thanks
Hi, in my understanding you can't directly, but you can retransform them to vector
(map #(into [] %) (partition 2 [1 2 3 4]))
is it answering your question?
Yees, I got it, you're the first I help !
😄 thanks @caumond
@francesco.losciale Or more concisely (map vec (partition 2 [1 2 3 4]))
question on clojure.spec
: when I do something like (s/def ::myspec ...)
what am I actually defining? What trips me is that that's not a variable, so I'm not sure how I should use it from another file. Doing something like:
(s/conform (s/coll-of myfile/myspec) collection)
doesn't work (use of undeclared var)when you declare s/def ::myspec you fullfill a https://clojure.org/guides/spec#_registry which key is the keyword
your example does not because s/coll-of does not seem to call the keyword
thanks, and how would I refer to that spec to conform some data in another file?
try
(s/def ::tst int?)
(s/conform (s/coll-of ::tst) [1 2])
I got it now! Your example wouldn't work for me, but :myfile/myspec
would! It's just a keyword!
thanks for the help @caumond! 🙂
to refer an external keyword, you need to specify the full qualify name
yes, that's it
have a look also to ::myfile/myspec syntax
very helpful to use :as
in your require
`
(require [myfile :as m])
::m/myspec
it was my last wednesday breakthrough, (;p
hahaha, very good points, thanks again 🙏
no pb, us guys are sleeping, so early I have opportunities to appear knowledgeable
Normally, when I have a hash-map, I can look up if a key exists and I can see all values. With a transient hash-map that does not work. How would I solve this?
(vals {:a 1 :b 2})
;; => (1 2)
(vals (transient {:a 1 :b 2}))
; Execution error (IllegalArgumentException) at robot-name/eval29220 (form-init8682869554046594837.clj:59).
; Don't know how to create ISeq from: clojure.lang.PersistentArrayMap$TransientArrayMap
I think Im complicating things here to solve this challenge
; Write a function, validate, which will check that :name and :glitter-index are
; present when you append. The validate function should accept two arguments:
; a map of keywords to validating functions, similar to conversions, and the
; record to be validated.
(def validation {:name validate-name
:glitter-index validate-index})
(defn validate
[validators suspect]
(and (get suspect key) ((get validators key) (get suspect key))))
or is this what you are looking for :
(defn validate2
[validators suspect]
(reduce-kv (fn[acc k v]
(and acc ;; The previous keys were validated
(contains? suspect k) ;; the suspect contains the key in question
(v (suspect k)))) ;; the value of that key in the suspect validates according to the validator function
true validators)) ;; you want to check all validators, so you reduce over them
(defn validate-name[name]
(print name)
(and (string? name) (> (count name) 3)))
I made this with some help of another personDoes it work?
yep
Are you sure? How did you test it?
with this in repl
(validate2 {:name validate-name} {:name "a"})
;; => false
(validate2 {:name validate-name} {:name "aaaaa"})
and this two give the right answer
do you experts agree ?
@christiaaan, I don't know too much about transient but it seems they are not compatible with all operations
usually, you have a x! version of operators
key
is undefined, what is it meant to represent?
a record looks like this {:name: "John Doe" , glitter-index: 2}
so as far as I see it , key is first name
and then glitter-index
Yup that makes sense. What's your question then?
my question is that I think Im overcomplicating things. Am I right with that ?
as far as I see if I have to check if the keywords are there and if they are not empty
(Besides any errors in logic) your solution is not valid clojure because key
is unbound. It does seem a bit too complicated but to be honest I can't tell where you're going with it, so I can't answer your question, sorry.
The description is a bit vague too (e.g. what does when you append
refer to?)
Anyway, the exercise seems to consist of two parts. Why don't you try completing them one by one? Leave the second argument aside and try to focus on the first sentence:
> Write a function, validate, which will check that :name and :glitter-index are
> present [in a record]
I will try that
I have a type: (defrecord Point [x y])
How can I get a list of all the protocols Point implements?
(ancestors Point)
#{clojure.lang.Counted java.lang.Iterable java.util.Map java.io.Serializable
clojure.lang.IObj clojure.lang.IRecord clojure.lang.Associative
clojure.lang.ILookup clojure.lang.IMeta clojure.lang.IPersistentCollection
java.lang.Object clojure.lang.Seqable clojure.lang.IKeywordLookup
clojure.lang.IHashEq clojure.lang.IPersistentMap}
✔️now, which one lets me do :keys [x y]
destructuring? :thinking_face:
ILookup?
user=> clojure.lang.ILookup
clojure.lang.ILookup
user=> (doc clojure.lang.ILookup)
Syntax error compiling var at (REPL:1:1).
Unable to resolve var: clojure.lang.ILookup in this context
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/ILookup.java
Where's the best place to find docs about protocols and interfaces from Clojure core and clojure.lang? https://clojurians.slack.com/archives/C053AK3F9/p1609680670002700?thread_ts=1609680257.001800&cid=C053AK3F9
I'm starting here: https://www.youtube.com/watch?v=vZtkqDIicqI&feature=youtu.be
I have input which gives out put in below way
(filter some? [[7 6 8] 3 4 nil nil)
([7 6 8] 3 4)
how can i get destructing out put like (7 8 6 3 4)
I suggest flatten
flatten should work but take a look at this discussion too: https://stackoverflow.com/questions/25182904/clojure-why-is-flatten-the-wrong-thing-to-use
@pavlos I ran this
(flatten [ 5 6 {:a "v" :b "a" } nil 4 nil nil 5 nil :a [ 2 3] ])
the result is expected, it did not destruct the map, but it destructed vector.. Is still fine right?
All that matters in the end is whether your solution gives you the expected result. In an exercise like this I think it's fine but in real world problems, when flatten is the most obvious solution then there's a good chance something is wrong with your data model.
you might try (flatten .......)
i.e. (flatten (filter some? [[7 6 8] 3 4 nil nil))
lemme try it here..
(flatten (filter some? [[7 6 8] 3 4 nil nil]))
seems to work
flatten is an old trick from lisp
hmm no luck
(defn validate
[validators suspect]
(every? #(contains? validators %) suspect))
(validate [:name] {:name "toto"})
it gives now false where I expect to be true
Keep simplifying the requirements until you can come up with a solution and build up from that!
e.g. a good starting point could be:
> Write a function that has a single input (the record) and checks that :name
is present in that record
The main caution about flatten
is that if you have anything more deeply nested than that, it usually flattens more than you want.
thanks
I hope I did now a good job
; Write a function, validate, which will check that :name and :glitter-index are
; present when you append. The validate function should accept two arguments:
; a map of keywords to validating functions, similar to conversions, and the
; record to be validated.
(defn validate
[validators suspect]
(every? #(contains? suspect %) validators))
the functions that the text is talking about
(def conversions {:name identity
:glitter-index str->int})
(defn convert
[vamp-key value]
((get conversions vamp-key) value))
yup, you're halfway there
contains?
is not very idiomatic for key lookup in maps (and it throws people off when it's applied to lists/vectors), get
is more natural
oke, changed it and why am i half way there ?
validators
needs to be a map, not a vector
> a map of keywords to validating functions
hmm back to the book
(defn validate
[validators suspect]
(every? #(get suspect %) validators))
(defn validate-name[] true)
(validate {:name validate-name} {:name "toto"})
gives now false
and now I Cannot check for :name
alone
it has to have a second thing into it
that's not a map
it is not ?
now im confused
I learned that a map look like this : `
{:key "value"}
and I have used that as far as I know
There’s also the faintly JavaScripty (flatten 1)
etc.
Nevermind, you're right
ok, no problem
I also thought you mean this :
(validate {:validator [:name]} {:name "toto"})
but then I think I need to rewrite this one
(defn validate
[validators suspect]
(every? #(get suspect %) validators))
The validator needs to be a map of keywords to functions
oke
so it needs to look more like the first version (`{:name validate-name}`) and less like the second (`{:validator [:name]}`)
(defn validate
[validators suspect]
(every? #(get suspect %) validators))
(defn validate-name[] true)
(validate {:name validate-name} {:name "toto"})
but then I wonder why this is given falsethe name is there and the validate function gives also true
every? works with sequences
got it I think
(defn validate
[validators suspect]
(every? #(get suspect %) (validators key)))
(defn validate-name[] true)
(validate {:name validate-name} {})
this works but here's the thing
what's the point of the validator functions?
shouldn't you be using those to validate the values?
to see if the name is according to a certain thing
yep, but the challenge is not saying what the name should do to be valid
or I have to make things up
I could make code to say it has to be a string and longer then 4 characters but that is made up
no idea if that is a problem or I have to freedom
it's an exercise isn't it? it's up to you
You can also move the logic of get
to the validator function
but then it wouldn't exactly check for membership
In Clojure? Or some 3rd party lib?
Clojure.
e.g. should this be true or false?
(validate {:name validate-name} {:name nil})
Returns ()
.
I would say false
btw this is the difference of contains?
and get
as well
(contains? {:name nil} :name)
=> true
but
(get {:name nil} :name)
=> nil
thanks
got a bug somewhere
(defn validate
[validators suspect]
(every? #(get suspect %) (validators key)))
(defn validate-name[name]
(and (string? name) (> (count name) 3)))
(validate {:name validate-name} {:name "aa"})
this gives true but 2 is smaller then 3 so it should be falseyou're not calling the validator function anywhere
you need to apply the function to the value of the record
(every? #(get suspect %) (validators key))
this does not work anymore
also what do you think (validators key)
does?
I thought that
I thought I get the key like name
out of it
key works on map entries, not whole maps
you can get the full key set of a map with keys
oke
then there is another problem
(defn validate
[validators suspect]
(every? #(get suspect %) (validators keys)))
(defn validate-name[name]
(and (string? name) (> (count name) 3)))
(validate {:name validate-name} {:name "aa"})
gives still true where I expect to be false
Good morning all. My cider repl started printing the entire stack trace every time a function is called and even while I'm typing. This is separate from the regular error stack trace. How can I disable this?
you're not using validate-name anywhere
how do expect it to be false? 😛
I see it
pff I have to think about that one.
I thought (apply validators keys)
could help me but it does not
ok so the values of validators are functions that you need to apply to the values of the record
yep
apply is a figure of speech, I'm not referring to the actual clojure function
and Im still thinking I have to do something with this part #(get suspect %)
yup, that's the culprit
im thinking that that one give me the function
#(get suspect %)
gives you the value of the record for a particular key
and then im stuck how I can pass the name or the glitter-index to it
one problem at a time
So if the key is :name
, what do you want instead of just #(get suspect %)
?
to actually use the validator
call it ?
yep but how?
normally I do somehing like this : (validate_name "John")
Correct but now you don't have access to the actual function name.
You have the key of the validator instead (`:name`), how would you get the function using that?
using get
?
yes, how would you write that in code?
so something like (get validators(get suspect %)
(get suspect %)
gives you the value that you want to validate so that's one thing on its own
you can get the function in a similar way: (get validators %)
oke,
So now that you have the function and its parameter, how do you build the actual call?
So I need
(every? #(get suspect %) (get validators %) (validators keys)))
?
i think this is an issue with an older version of CIDER. Its making a call to get the clojure-docs and its failing
the syntax of every?
is (every? f coll)
I saw it when I tried that one
(defn validate
[validators suspect]
(and (every? #(get suspect %) (validators keys))(every? #(get validators %) (validators keys))))
still do not work as I expectbe back after dinner/supper
thanks so far
No offense, but it seems to me like you try random things when you get stuck. Try to understand why stuff doesn't work first instead.
i take no offense
I was thinking about two clauses and combine them with a and
so the keys must be there and the validating must return true
otherwise the record is not valid
(and (every? #(get suspect %) (validators keys)) (every? #(get validators %) suspect)))
looks better to me but no everything is false and the validate function is still not called
Still think I miss some knowlegde what the brave book is trying to teach me
I can't follow your train of thought
we have 2 things to test if the record is valid
what you want to do is: 1. for every key in validators 2. validate the value of record for that key
1. the keys schould be there
2. test if the value of the keys is valid according to a function I made up
1. is done by this piece (every? #(get suspect %) (validators keys))
, Right
2 is stil something I think I miss a piece
you might not need 1
because if the key isn't there the validation will also fail
but that's another story, let's keep it for now
ok, try this out:
(and (every? #(get suspect %) (validators keys)) ;; key exists
(every? #((get validators %) (get suspect %)) (keys validators))) ;; value is valid
the syntax is really awkward (it's not how I would have done it) but it works
You can try implementing a saner alternative using merge-with
or reduce-kv
merge-with is probably the most straightforward
I'm on the latest version available on melpa (20210102.631). Never experienced this before and I suspect I enabled it when typing some code while emacs was expecting a shortcut command.
Just noticed I no longer have a *cider-error*
buffer even after restarting emacs and my repls.
https://github.com/clojure-emacs/clojuredocs-export-edn/issues/3 is where i was following along
there's also the "dumb" version:
(defn validate
[validators suspect]
(and
((:name validators) (:name suspect))
((:glitter-index validators) (:glitter-index suspect))))
if you evaluate (/ 1 0)
and get an error do you then have a buffer *cider-error*
?
Not sure which channel to ask this in, but since this is such a friendly one: I've been using https://github.com/jarohen/chord and http-kit for websocket stuff for the past few years, and since it always did what it needed to do, I never bothered looking at anything else. But if I go to the latest version of http-kit, things break down, and since chord doesn't seem very active anymore, maybe it's a good time to switch. What do people use for working with websockets (frontend and backend)?
no, cider-error buffer doesn't come up.
Also, M-x nrepl-log-expand-button
states: Cannot open doc string file "/home/.emacs.d/elpa-26.3/cider-20200915.1827/nrepl-client.elc
Looks like it's looking for the old version
strange. can you delete your CIDER version and reinstall? not sure what's going on there but if there's two versions at play it might be really weird bugs
thanks
I could even been
(defn validate
[validators suspect]
(every? #((get validators %) (get suspect %)) (keys validators)))
yes that skips the first check
but it's done implicitly by the validator so in practice it's the same
I saw it when trying
I hope I can find out how reduce can make this easier to read
merge-with
and reduce-kv
will not necessarily make it easier on the eye
But they will allow you to break it down into parts
oke, reading now the page where reduce-kv
is explained
I hope im on the right track
(defn validate2
[validators suspect]
(reduce-kv (fn [v s] ??? ) {} validators))
I still have to figure out what must be placed instead of the ??the fn takes 3 params
m k and v
??
see the examples
moment, you mean with k the key and with v the value
m k and v are conventions, you don't have to call them that but it helps you understand which is which
see the examples
yep, I have them before me if I try to make this work
oke,
I have this now :
(defn validate2
[validators suspect]
(reduce-kv (fn [s k v] ) {} suspect))
where s is the suspect , key is the key of the key I want to test and v is the validation function
you can't choose what k and v will be, they will be drawn from the last argument (suspect in your case)
I know I try to explain my thought process
oh ok, go on then
now I could check if the key exist
so rewrite this part: (every? #(get suspect %) (validators keys))
chips, stuck again
wait a minute, if key is the key of a suspect for example the name then that is the k now
so I think I can do something like this : (if #(k (vl keys) .... )
haven't tried it but sente looks like a good fit https://github.com/ptaoussanis/sente
nope, this is more then I can chew now
(reduce-kv (fn [vl k v] (if #(k (vl keys) #(get vl % k ) ) ) {} suspect))
but nested # are not allowed
and this looks better
but give a function
yeah, sente was around already when I chose chord. At the time I found sente was overkill
I need a break
this is given nill
(defn validate2
[validators suspect]
(reduce-kv (fn [vl k v] (if #(k (vl keys)) (#(get vl %) k) false )) {} suspect))
Right now I very lost on what is what
every? #((get validators %) (get suspect %)) (keys validators)))
the first part #((get validators %)
will be #(get vl %)
and the part get suspect%)
is #(k (vl keys)
so both would be #((get v1 %) (k (vl keys)
I make somewhere a big thinking error :
(defn validate2
[validators suspect]
(reduce-kv (fn [vl k v] (if #(k (vl keys)) #((get vl %) (k (vl keys)) false ))) {} suspect))
(defn validate-name[name]
(print name)
(and (string? name) (> (count name) 3)))
(validate2 {:name validate-name} {:name "aaaa"})
still give a function so somewhere I forget a argument
and I do not see where
can you give me a hint @pavlos
he. why here a null pointer exception
(defn validate2
[validators suspect]
(reduce (fn [vl s] ((get validators vl) (get suspect s ))) false (keys validators)))
(defn validate-name[name]
(print name)
(and (string? name) (> (count name) 3)))
(validate2 {:name validate-name} {:name "a"})
(Get validates vl) is called with false the first run, presumably returns nil and you invoke that
how do I do #(nth % 1)
in a way that puts %
in the last position so that I can use it in a ->>
macro? (In haskell it would be something like flip nth
)
oke, I thought the 3th argument should be the standard value
I know that I can define it myself, or I could use as->
(but as->
doesn't play along with debux
's debug macros). Is there an idiomatic way of writing it for ->>
?
You can also use the ->
macro, but that makes it the first argument for the whole thread.
yeah, the problem is that all of the other step would like the last argument
it's really ugly, but you could do (#(nth % 1))
I did a complete reinstall of emacs and CIDER, but I'm still not getting a cider-error buffer. The clojuredocs error still comes up as well.