This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-12-10
Channels
- # adventofcode (9)
- # bangalore-clj (1)
- # beginners (130)
- # boot (6)
- # cljs-dev (8)
- # cljsjs (12)
- # cljsrn (3)
- # clojure (33)
- # clojure-brasil (3)
- # clojure-korea (4)
- # clojure-russia (150)
- # clojure-sanfrancisco (4)
- # clojure-spec (159)
- # clojure-uk (3)
- # clojurescript (100)
- # code-reviews (9)
- # core-async (1)
- # datascript (3)
- # dirac (58)
- # hoplon (8)
- # jobs-discuss (10)
- # luminus (18)
- # om (2)
- # onyx (14)
- # protorepl (19)
- # re-frame (34)
- # reagent (28)
how would i go about making this work (= “pos?” (let [f pos?] (??? f)))
str works if called on the original function, but not if its a … reference?
googling around is getting me no where
This is on clojure version 1.7 since the repl for Android hasn't bumped to the latest version
Thank you @seancorfield for the resources!
@drewverlee I forgot to mention you in my replies. Is what I got similar to what you got?
@gdeer81 i get the same. I’m curious how i might get just the plan name. but its not that big of a deal.
The issue is that when you ask clojure for the details of something it is very precise
@gdeer81 gotcha. i can use the detailed name just as well.
Too late, I've already spent an hour trying to figure out the regex that will match every possible name between the $ and @ in the long name
oh no
I can calculate it for 2 numbers like this :
(defn gcd [a b]
(if (zero? b)
a
(recur b (mod a b))))
(defn lcmv
[a b]
(/ (* a b) (gcd a b)))
but how can I make it work with more then 2 numbers. Please some tips and not the answer
@raspasov returning the simple name of a function as a string (let [f inc] (stringify-var-name f)) => "inc"
although i am only 34 and on a day-to-day basis i need at least 6 hours to sleep, that is, waking up with less is near impossible lately
although sometimes it's hard 😞. like when you are sick or in pain. so not quite true that anyone 😞
but generally speaking i always tell people that they should learn to meditate on a basic level and they would then be able to control their sleep much better
I'm getting an error message I can't figure out for this code:
(defn transit [we]
(let [transform (comp
(map (partial choose we))
(mapcat (fn [me] (make (:choice me) we me))))
reduction (fn [acc me]
(let [me-gen (get me :generation 0) acc-gen (get-in acc [0 :generation] 0)]
(cond
(= me-gen acc-gen) (conj acc me)
(> me-gen acc-gen) [me]
:else acc)))]
(transduce transform reduction [] we)))
Error:
Exception in thread "LWJGL Application" clojure.lang.ArityException: Wrong number of args (1) passed to: core/transit/reduction--73
JK "f should be a reducing step function that accepts both 1 and 2 arguments, if it accepts only 2 you can add the arity-1 with 'completing'."
How can I test this function with clojure.test :
(defn read-data-painting
"Reads the title, description, date , collection, colors and url of a image"
[id]
(let [art-objects (-> (str " " id )
(client/get {:as :json :query-params {:key (env :key) :format "json" :type "schilderij" :toppieces "True"}})
:body
:artObject)
name (-> art-objects
:principalMakers
first
:name)
description (:description art-objects)
date (get-in art-objects [:dating :year])
collectie (first (:objectCollection art-objects))
colors (:colors art-objects)]
{:id id :name name :description description :date date :collectie collectie :colors colors}))
I think I have to mock up the client-get part. Do I have to copy the whole file into a test function or can I do it another way?
it doesn't say in the documentation at http://clojure.org/reference/transducers or https://clojuredocs.org/clojure.core/transduce what the arity-1 overload on f actually does. What is it used for?
yeah, sorry, i shouldnt be trying to answer questions during a late night binge -- best i can say is give it a 1ary impl and put a print in there 🙂
@roelofw I think function should be decomposed. It has too many responsibilities. Something else should grab Json that you want to deconstruct. The Json should be past into your function. Then you have a separation of responsibilities. I.e. SRP. If you follow that the test should become easier
@roelofw Are you trying to simulate client/get
for a test condition?
@bigkahuna so seperate function that takes the id and returns the response ?
I think you can get started with (with-redefs [client/get (fn [& args] mock-value)] …test-code-here...)
but remember that with-redefs
is only for very simple scenarios
and I can use that instead of the client/get so I copy the function and change that @kumarshantanu
@roelofw Yes, with-redefs
lets you temporarily mock vars
If the client/get is a REST call then it should be in its own function IMO. You can pass it into the function as well as the Id. That way you can mock it to return a stock Json output so your test can then concentrate on testing that the function destructs the json as expected.
I think ideally (as @bigkahuna suggested) you should define your fn thusly: (defn read-data-painting [http-get id] …)
, so that you can call http-get
fn instead of client/get
, and during test you can pass a mock version for http-get
Also bear in mind that when testing, you ideally want to test functions in a pure fashion so any collaborators should be externalised or to put it another way there shouldn't be any side effects. Having the REST call embedded within the function is a side effect which makes your function harder to test than it should be. You shouldn't need a real endpoint to test your function's logic. By passing in the function for REST means the function for destructuring can be tested in a pure fashion. In an OO world, this would be seen as externalising your collaborators so they can be mocked.
@seancorfield is there a way in Clojure to define my MySQL relationships in an ORM-like model? Or do I create tables and their relationships strictly in my database?
I’m wondering if there is a way when I run my application to build all of its database table dependencies?
@kyle_schmidt think about what that looks like in a functional world. If you have data and functions then what you are asking is can I build a database from a data model. This can be done and is part of the concept behind Datomic. However, not sure anyone has written anything to auto generate a relational database schema from a Clojure data structure.
@kumarshantanu I need that url call there because it depends on the id . So I think I cannot make it pure
@agile_geek It sounds like a record might be a good abstraction for a sql table?
@kyle_schmidt yeah or just a plain map
I'm sure it would be possible to generate a relational schema from a plumatic schema or Spec definition
@agile_geek Do you know a good way to test a function which is not pure because It's needs a call to a external source ?
It's not ideal but you can use with-redefs
to redefine the fn that calls the external source but that's not ideal
Or you can pass the fn that calls the source as an argument to your function.
In either case in the test you can supply a dummy fn that returns the data you want for your test
Oke, so make for all api calls seperate functions and in the test make a function that return the same as the real function, @agile_geek ?
Yes. Make the api call fns arguments to the function you want to test so in the production code you pass the real api fn and in test u pass the dummy one. Also you can use multiple arity versions of production code. One arity has the api fn and one that doesn't. The one that doesn't calls the one that does passing the real api fn.
In the test you use the version with the extra api call argument
Oke, I have to think how to do that. I think I can better look for a bette way to achieve the same
This is a pretty std way to mock external dependencies and is quite powerful
oke, I will think about it . At this moment I understand what you mean but do not see how to make it work in real
Ok have a think about it. Basically you are using high order functions. Passing a function as an argument to another. Good luck
@kyle_schmidt I’m the wrong person to ask about ORM-like stuff — I’ve given conference talks on why ORM is evil and I’ve ranted and raged on mailing lists about that topic too!
I would just use hash maps for the rows and avoid formal “modeling” as much as possible, to be honest. I don’t even like FK constraints: I treat the database as a dumb persistence system for the most part.
@agile_geek oke, then I have to hit some books to learn more about higher functions work in clojuer
that is a subject I did not see in the clojure koans or the first challenges of 4clojure
You've probably already seen simple examples of passing a fn to a fn
@seancorfield: interesting. So do you build your tables in your DBMS and then build an application that references the tables? Separating data from logic?
@kyle_schmidt The DBA is responsible for making sure the database schema is efficient and correct (in terms of data types). They don’t like FK constraints either so we’re in agreement there. Inside Clojure, tables are just sequences of hash maps (and rows are just hash maps). At the boundaries of the system, we read hash maps from the database and write data back to the database.
After all, our application is just a set of functions that operate on data.
Gotcha. I guess I'm speaking from the DBA and engineer perspective since I'm in charge of both. Was looking to see if I could manage this somehow in one place
I build my apps like that even without a dedicated DBA. Let relational databases do what they do best
Not sure what “duplication” you’re trying to avoid tho’ @kyle_schmidt ? Unless you want “specs” of your tables, you’re not really going to have anything in Clojure that duplicates the DB schema… and I wouldn’t consider the Clojure / DB edge to be a system boundary that needed validation, to be honest (unless you’re specifically dealing with a 3rd party system’s DB that you can’t trust — but then you didn’t control the schema for that anyway).
@agile_geek oke, so your are talking about this read_date(f ) where f is in production the client-get and in test only something like this {:id 1 :name '" Roelof"} as a example
I agree with @seancorfield. I would put Specs on the api side of my app but not the outbound database calls as you can control the data shape yourself.
@roelofw a fn that returns that map in test but yes...except your syntax for read_date is odd in that example
(read-date f)
— stop using _
in Clojure names!
Then in tests you can say (read-date (constantly {:id 1 :name ”Roelof”}))
Thanks @seancorfield struggling to type fast on phone... especially after 3 G & Ts 😉
Coming from a Python background and the SqlAlchemy module I can create Python classes which act as an abstraction and spec of SQL tables. If I change the spec of a class then it's reflected in the database without me having to login to the database itself
And call methods on these classes which are SQL queries under the hood
But I shouldnt worry about spec'ing out the tables in Clojure because it complects data and logic? I should just write functions that query those tables.
There are no classes in Clojure.
This is what I meant about ORM being evil.
In Clojure, it’s just data. If you change your DB schema, when you load a row, it just gives you data.
If you add a column to a table, that hash map has the extra key already.
If you remove a column, that hash map no longer has that key. If you change the data type of a column, the hash map just has a different value type for that key.
There is no code corresponding to the schema. In an OOP language, you have to specify code — an attribute definition — for every column.
(and you have to have a class for every table).
Gotcha, sorry for making you have to spell it out for me but I definitely see where you’re coming from now.
OOP is what creates that extra work, that duplication. ORM is a solution to a problem that simply doesn’t exist in FP.
Yeah a poor soln to Object Relational impedance mismatch
interesting! Ya that makes a lot of sense. I like that approach a lot!
With java.jdbc
, you can say (jdbc/get-by-id db-spec :table-name the-key)
and that’s it — it’ll get you a row of data from any table, given the PK. Nothing else is needed.
(jdbc/insert! db-spec :table-name map-of-data)
will (attempt to) insert the given hash map as a row in the table. As long as you have no additional keys in the map and you aren’t missing any non-default keys, it’ll just work. The JDBC driver itself does all of the work for you.