This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-12-29
Channels
- # adventofcode (11)
- # beginners (98)
- # boot (2)
- # cider (3)
- # clara (3)
- # cljs-dev (15)
- # cljsrn (2)
- # clojure (122)
- # clojure-austin (4)
- # clojure-russia (1)
- # clojure-spec (2)
- # clojurescript (30)
- # css (6)
- # cursive (5)
- # docs (1)
- # fulcro (4)
- # hoplon (118)
- # keechma (3)
- # leiningen (5)
- # lumo (1)
- # off-topic (28)
- # onyx (6)
- # re-frame (4)
- # reagent (1)
- # reitit (1)
- # shadow-cljs (53)
- # sql (1)
- # unrepl (1)
Is there a more idiomatic way to call all functions in a sequence and return their values than (map #(%) seq-of-fn)
?
Something like (map call seq-of-fn)
would look a bit nicer. Just an example, I know call
doesn't exist.
I wouldn't describe your solution as unidiomatic though, choose what's most tasteful to you
Thank you @U053XQP4S
Suppose I have:
{"foo" "val1", "bar" "val2"}
and I would like to turn it into {:foo "val1" :bar "val2"}
, so essentially mapping a map to another map where the target map uses symbols instead of strings for keys...
this is what you’re looking for 🙂 http://clojuredocs.org/clojure.walk/keywordize-keys
one approach here can be to extract keys
and vals
, keyword
all the keys and zipmap
back with vals
@hans378 How familiar are you with the functional style of programming?
w00t
(zipmap (map (fn[k](keyword "myns" k) ) (keys input)) (vals input))
{:myns/foo "val1", :myns/bar "val2"}
If you’re used to OOP/imperative-style, I’d recommend trying out the reduce-kv
approach pcbalodi mentioned. https://clojuredocs.org/clojure.core/reduce-kv
@manutter51 i want to get away from that style 🙂
Though zipmap
is pretty cool too 🙂
@manutter51 i'm one of those java guys that wants something different
I’m certainly one
The other day at work, I was building something that required adding on to a co-worker’s code, and I looked at his code and thought “I have no idea what this code is doing.” Then I thought, “Wait a minute, this is Clojure. I can figure it out.” And sure enough, just stepping through it I could see exactly what it was doing, and then the intent became more obvious.
Not an experience I was used to having in Java. (PHP was worse though.)
lol 😄
I once had to take over maintenance of some Perl code written by a guy who had just become Catholic. He named his subroutines after Catholic saints. I kid you not.
if somebody does java and uses a functional-style of programming that improves readabilty a lot... still java requires a lot of ceremony
I think Clojure is one of the better languages if you want to read code, I feel comfortable in checking out any open source lib and reading the code.
@manutter51 hahaha really
Hi @amit5881, you need zipmap
to go from (:first :second :third)
and ("9" "2" "5")
to {:first "9" :second "2" :third "5"}
. To answer your full question, you need to map
that zipmap
over your inputs, like this: (map zipmap (repeat '(:first :second :third)) '(("9" "2" "5") ("1" "2" "3")))
. (The repeat
is needed since you want to zipmap
the same (:first :second :third)
with both of your lists.)
@manutter51 that is almost as crazy as naming your function-results after http status codes
reminds me of this - https://github.com/Droogans/unmaintainable-code
What's the idiomatic way to take a map and to produce another map with a given subset of the keys (each key having the same value as in the original map)?
select-keys
@manutter51 Thank you!
Three HTML tag names conflict with clj/cljs names: map, meta, and time. My new HTML library (ironically named Tag) wants to provide macros for all tag names.
I get warnings
`WARNING: meta already refers to: #'clojure.core/meta in namespace: tiltontec.tag.gen, being replaced by: #'tiltontec.tag.gen/meta
` when I compile.OK, just warning, but looking ahead I will be shadowing (worst of all) map.
@hiskennyness are you familiar with refer-clojure
? https://clojuredocs.org/clojure.core/refer-clojure
As long as your usages are namespaced, you should be ok with using them elsewhere, and refer-clojure
will let you silence those warnings.
I had the same conflict with the keyword :type (which sneaks in as an attribute for input tags, inter alia) but there I could ns qualify with ::type and (I think!) avoid warnings or shadowing.
Yes, thx, I know about refer-clojure, but with something as ubiquitous as map I would not want to lose that. Lemme read up on refer-clojure. Thx
OK, so refer-clojure muffles the warning and then I just have to code clojure.core/map where I want to use that. Then my users only have a problem if they want to code those tags?
In these situations it’s common to alias clojure.core to something like c, so you can use c/map instead of clojure.core/map
they should be requiring your code with an alias anyway, in which case the issue doesn't come up
and if they want to use it without an alias, they can also use refer-clojure with :exclude
None clojure question. Why not have a front end client just send a database query directly to retrieve the data it wants rather then going through a “restful” API. I dont feel like i see this very often, or maybe i do and i dont recognize it?
Is this the same question as “why have an interface” or are their database and network specific concepts at play?
@drewverlee What about security? SQL injection attacks etc?
@seancorfield Good points. So your server can do some authentication and authorization. But past that you trust them 100% with the data. Or maybe you just restrict them to a set of views and read only.
I’m going through a phase where i’m having to write a lot of. /customers/{id}/widgets -> basically turns in to “Select * from customers…” And i’m trying to figure out why i’m using a URL or a post body to convey something less declaratively then the SQL query itself.
projects like http://graphql.org/ and om.next were created to remedy that, and I’m sure there are tons of others
Is om.next different then reframe in that regard? I dont know much about either but people often consider them together.
drewverlee - I’ve felt that pain too. Like, why is the DB doing all this validation and roles and everything just to recreate it in between?
@drewverlee Well, you could write a generic route handler for /{entities}/{id}/{thing}
and "trust" the entities
as a table name, id
as the PK and so on...
But watch out for someone requesting /mysql.user/1/...
kind of stuff and lifting all sorts of sensitive data out of your DB.
And then there's the whole "Bobby Tables" thing to watch out for if you're trusting user input to help you generate SQL 🙂
Essentially you need a DSL inbetween the client and the DB to prevent problems. And that DSL can't be "raw SQL" because that's too powerful.
Thanks for talking to me about this. I’m sure there are concrete limitations that i’m not seeing, otherwise i feel this approach would be used. Your saying that SQL is to powerful, but what i’m interpreting that statement to mean, is that the client should only be able to interact with the data in limited ways. Aren’t there ways of limiting access to the database that still involve the main language being SQL? For instance, a database role can be restricted to certain actions, tables and views… right? What if users were given the passwords to limited roles, so your limiting the scope of what they can do, but not defining it as precisely as i feel we do with APIS.
SQL GRANTs are not particularly granular -- that's one problem -- and another is that the client, which is plain text by definition in JavaScript, would have to contain the usernames and passwords for any DB access and therefore "anyone" can write a client using those credentials to pull any and all data out of your DB that the client theoretically has access to. If you app has "users" and they need to "login" to interact with the DB, those user accounts have to be in the DB and thus their raw data is available to anyone -- and if you have encryption, the client needs to have that encryption logic in it, in order to interact with the DB so that's public too.
Most apps need more than SELECT access so you'd have to have some UPDATE access and that means anyone has that level of access to those tables and can write unchecked into your DB.
I can imagine an application between the client (browser) and the database that could handle the authentication and then pass the client a authorization token with its specific permissions on the database. Does that seem reasonable? I briefly read about SQL Grants, at a glance you can specify INSERT, SELECT,UPDATE,EXECUTE over a specific table or view. So, as you suggest, i think more work would have to be done in creating custom tables/views for clients. Then, my idea would be to give more free reign within those views as to what clients code do. Of course, having a view for every situation would be very inefficient if i have to create them per business domain. e.g per customer. But it seems reasonable that this “authorization role” could be part of the the additional information the server has (that maybe the client doesn’t) and passed on behalf of the client. Your right, i wouldn’t want the client (browser) knowing the encryption logic!!! So I would defiantly want a back end for this. Im going to read around this subject more. If feel like GraphQueryLanguage is less expressive then SQL and currently its odd to me that there is no way to just re-use SQL. (not that i think SQL is the only query language mind you). Just that, having two query languages SQL and GraphQL feels wrong. Of course GraphQL is more then just a query language… Anyway, thanks again for talking to me.
> I can imagine an application between the client (browser) and the database that could handle the authentication and then pass the client a authorization token with its specific permissions on the database. Does that seem reasonable? That application needs to mediate nearly all interactions between the client and the database tho'.
As you say, restructuring your DB so that it reflects every aspect of the security requirements of the client's UI/UX is going to lead to a very complex and inefficient database (and you'd then need a whole bunch of business logic inside the database as a set of stored procedures and triggers -- which is a pretty horrible way to manage your business logic from a version / change management side).
Heh, yeah, expose your entire CouchDB to the Internet... 😐
also if you just expose your db to the front end, it will be harder to build further features on top of it.
Using Compojure I am parsing a POST with a JSON body with a structure {"user":"name"} and the following defroutes line (POST "/login" [user :as {db :connection}] (login db user))
sets user to nil. Am I reading the documentation wrong?
If I destructure the body element I can parse it in the function.
doesn’t compojure use normal destructuring? the way it would work with normal destructuring would be {db :connection :as user}
unless I’m totally misreading this
then user would be the hashmap that had db under :connection
The docs say there is special decoding for some fields. I read it as the body for POSTs but it may be parameters only.
I am pretty sure I need the :as
before the {db :connection}
that’s not how :as works
The db is coming through fine. The problem is the user.
right, user :as
says “look up the keyword :as on the map, bind the result to the symbol user”
:as user
says “bind the entire data structure being destructured currently to the symbol user”
Hmm, a careful parsing of destructuring docs would seem to be in order.
I don’t like the way compojure defroutes subtly changes the way destructuring is used - to me it obfuscates things
I mean mostly it’s the same as destructuring in a binding vector but it’s just different enough that I forget the subtleties as a non-compojure-user who occasionally tries to assist compojure users
what is the best way to test a rest api (liberator, but i am not sure that matters) - i see kerodon .. but is there anything that would actually test a route given an input to get a certain result?
if using ring, I like to pass a hash-map replicating the request map that would come in, and call the handler with that, then make is assertions about the data that gets returned
this way you can skip a bunch of stateful / http using stuff sicne that should be covered by the ring unit tests
there’s a ring library for mocking requests but really you can just use a hash-map literal
hmm seems liberator is more complex then compojure app .. i made this app 3 years ago and look liberator hasn't hardly been touched in 3 years
I’m not talking about compojure though - this approach works with any lib that uses ring
mind you when I say “handler” I mean the function that handles your request, including routing and calling the apropriate function for that route
it’s too bad that liberator isn’t being maintained