Getting clojure.core$count cannot be cast to java.lang.Number error for defined variable count
(defroutes jobs-routes
(context "/jobs" []
(POST "/jobValidation" [name status req] (insert-job jobName jobStatus req)))
In this method I've define a variable count to store the value of total count from the query
(defn insert-job [jobName jobStatus req]
(let [count (db/insert-job {:job-name name :status status})])
(when (> count 0) (println (format "true" )))
(insert-job req) ;
)
Query: db/insert-job
-- :name insert-jobWithValidation :? :*
SELECT count(*) FROM job_history WHERE job_name = :job-name and status = :status
Problem
I want to check that whether If I'm getting out value greater than 0 so I can print something any if count is any positive value then I can perform something new
Your let block has no body, you're closing it right after definitions vector:
(let [count (db/insert-job {:job-name name :status status})])
Note that you are shadowing core function count here.
So when you call this line:
(when (> count 0) (println (format "true" ))), the value of count is count function:
count
=> #object[clojure.core$count 0x69c6a700 "clojure.core$count#69c6a700"]
(> count 0)
Execution error (ClassCastException)
class clojure.core$count cannot be cast to class java.lang.Number
There are some other errors and style inaccuracies:
the names of your variables don't match (jobName jobStatus vs name status)
you're calling (insert-job req) with only one argument, but this function has three
(> ... 0) is pos?
(format "true") is just "true"
Possible fix (maybe you will still have to modify it somehow):
(defn insert-job [job-name job-status req]
(let [my-count (db/insert-job {:job-name job-name :status job-status})]
(if (pos? my-count)
(println "true")
(insert-job job-name job-status req))))
that is probably because of your hugsql query header:
:? :* - returns the rowset, which is not a number.
maybe :? :1 would be more suitable here. Anyway, the query doesn't return a count(*), it rather returns a hash-map (in case of :1) or a list of one hashmap (in case of :*), you would still need to retrieve the value from there.
Something like that (untested):
-- :name insert-jobWithValidation :? :1
SELECT count(*) as amount FROM job_history WHERE job_name = :job-name and status = :status
(defn insert-job [name status req]
(let [res (db/insert-job {:job-name name :status status})]
(when (-> res :amount pos?)
(println true))
(insert-job req)))
UPD: omg, let with no body, indeed, #Martin Půda, thanks )
i would say, what you want is something like that:
-- :name count-jobs-by-name-and-status :? :1
SELECT count(*) as amount FROM job_history WHERE job_name = :job-name and status = :status
(defn insert-job-if-not-exists [name status req]
(if (->> {:job-name name :status status}
db/count-jobs-by-name-and-status
:amount
pos?)
(println "job already exists")
(insert-job req)))
Related
If I have a table {field1=1,field2=0} (0: ascending order, 1: descending order)
I want to get a function:
function(x,y)
return x.field1 < y.field1 --there 0:'<',1:'>='
end
field1 in the table and the sorting rule can be injected in the function.
How to generate this code dynamically?
Let's talk about more than just the code generation approach! As in the question, consider the need of a function:
function (x, y)
return x.field1 --[[ < or >= ]] y.field1
end
For the sake of the examples assume that we have global variables:
FIRST = {field1 = 3}
SECOND = {field1 = 5}
Branching
The simplest solution (perhaps also the most typical?) that comes to my mind is a verbose if:
function foo (x, y, o)
if o == nil or o == "asc" then
return x.field1 < y.field1
end
if o == "dsc" then
return x.field1 >= y.field1
end
error("Unknown option")
end
-- Example:
foo(FIRST, SECOND, "asc")
foo(FIRST, SECOND, "dsc")
Note that early returns make else unnecessary in this case but it might not always be true.
Anonymous function
But, hey, what's that? What if rather than a string option we pass something more bizarre like... something that can be called? Let's go with a simple function this time:
local asc = function (a, b) return a < b end
local dsc = function (a, b) return a >= b end
function bar (x, y, compare)
compare = compare or asc
return compare(x.field1, y.field1)
end
-- Example:
bar(FIRST, SECOND, asc)
bar(FIRST, SECOND, dsc)
bar(FIRST, SECOND, function (a, b) return a < b end)
Higher-order function
The previous example doesn't really look that good with a such simple operation, but let's take it as a base and let's create a function that will return us the desired function:
function make (compare)
return function (x, y) return compare(x.field1, y.field1) end
end
-- Example:
local asc = make(function (a, b) return a < b end)
local dsc = make(function (a, b) return a >= b end)
asc(FIRST, SECOND)
dsc(FIRST, SECOND)
Actual generation
Now then, let's try something closer to code generation. Lua gives us the ability to load chunks as we go with load* function family.
Please note that load in 5.1 is different from load in 5.2 or load in 5.3. In 5.1 you want to use loadstring instead of load.
function generate (op)
return load(string.format("return function (x, y) return x.field1 %s y.field1 end", op))()
end
-- Example:
local asc = generate("<")
local dsc = generate(">=")
asc(FIRST, SECOND)
dsc(FIRST, SECOND)
Hello this is the error i am receiving and cannot seem to spot what is wrong with my SQL statement. Figured a extra pair of eyes couldn't hurt
UPDATE sales SET state_name =?, sales_id =null, sales_timer =null where entity_id =?
here is the function that houses that statement
(defn release
[m]
(db/execute!
(core/db)
(str "UPDATE sales SET state_name =?, sales_id =null, sales_timer =null where entity_id =?")
[(name (m :current-state))
(m :entity-id)]))
and here is the error we receive the error from
(defn get-unfinished-sales
[]
(db/query
(score/db)
(str "select * from sales where state_name = 'in-progress'")))
(defn unlock-sales
[usales]
(doall (map (fn [sale]
(->
(score/put-batch
{:user core/system-user
:messages [{:entity-id (sale :entity-id)
:message-type "release"
:message {}}]
}
:sales)
(core/log-result-if-failure))) usales)))
(defn
run
[& args]
(->>
(get-unfinished-sales)
(filter (fn [row] (not (nil? (row :sales-timer)))))
(filter (fn [row] (> (t/in-hours (t/interval (row :sales-timer) (t/now))) 1)))
(unlock-sales)))
Your call to db/execute! should put the SQL string as the first item in the vector with the parameters:
(defn release
[m]
(db/execute!
(core/db)
["UPDATE sales SET state_name =?, sales_id =null, sales_timer =null where entity_id =?"
(name (m :current-state))
(m :entity-id)]))
I want to count elements in a list that have the same ID
(defrule UniqueIdentifier_testfile
(P (ID_Jess ?id_context) (k $?ass))
?c <- (accumulate (bind ?count 0) ;; initializer
(bind ?count (+ ?count 1)) ;; action
?count ;; result
(and
(P (ID_Jess ?id_as1&:(member$ ?id_as1 ?ass)) (id ?id_ref1))
(P (ID_Jess ?id_as2&:(member$ ?id_as2 ?ass)) (id ?id_ref2))
(and (neq ?id_as1 ?id_as2) (eq ?id_ref1 ?id_ref2))
)
) ;; CE
(test (neq ?c 0))
=>
(printout t "UniqueIdentifier_testfile --> FIRE ! (" ?id_context ":P).id :{"?ass"} -> 'id' not uniques" crlf)
)
As you can see :
a fact of type P has a "real" ID which is reified in the slot "ID_Jess" and an other slot "id" which I'd like to test if it is unique too.
In modelling words :
(deftemplate P
(slot ID_Jess)
(slot id )
(slot m )
(multislot k )
)
It all looks fine, and "compile" allright. But the execution gives me that error :
Jess reported an error in routine HasLHS.addPattern.
Message: Variable used before definition: c.
Program text: ( defrule UniqueIdentifier [...]) at line 70 in file <eval pipe>.
at jess.HasLHS.a(Unknown Source)
...
Anybody got a clue why that ?c is not defined after the accumulate has been executed ?
Even if the condition is never fulfilled, the counter (?count) which is binded as result will at least be a defined '0'.. Am I wrong ?
If I specify an easier conditional element, the accumulate function executes as expected..
Working on the following example in "Clojure in Action" (p. 63):
(defn basic-item-total [price quantity]
(* price quantity))
(defn with-line-item-conditions [f price quantity]
{:pre [(> price 0) (> quantity 0)]
:post [(> % 1)]}
(apply f price quantity))
Evaluating on the REPL:
(with-line-item-conditions basic-item-total 20 1)
Results in the following exception being thrown:
Don't know how to create ISeq from: java.lang.Long
[Thrown class java.lang.IllegalArgumentException]
It appears the exception is being thrown after the apply procedure is evaluated.
The last argument to apply is supposed to be a sequence of arguments. In your case, the usage might look more like this:
(defn with-line-item-conditions [f price quantity]
{:pre [(> price 0) (> quantity 0)]
:post [(> % 1)]}
(apply f [price quantity]))
apply is useful when you're working with a list of arguments. In your case, you can simply call the function:
(defn with-line-item-conditions [f price quantity]
{:pre [(> price 0) (> quantity 0)]
:post [(> % 1)]}
(f price quantity))
I already sent the bug to fsbugs#microsoft.com but I also added this link to letter for additional description, code highlighting, discussions and maybe someone find some way to avoid it, because I really like it and want to use.
Code :
<# seq {for a in db.ArchiveAnalogs do
for d in db.Deltas do
if a.ID = d.ID then
if a.Value > d.DeltaLimit then
yield a.Date, d.AboveMessage
else if a.Value < d.DeltaLimit then
yield a.Date, d.BelowMessage}
#> |> query |> Array.ofSeq
Same error messages with update :
<# seq {for a in db.ArchiveAnalogs do
for d in db.Deltas do
if a.ID = d.ID && a.Value > d.DeltaLimit then
yield a.Date, d.AboveMessage
elif a.ID = d.ID && a.Value < d.DeltaLimit then
yield a.Date, d.BelowMessage}
#> |> query |> Array.ofSeq
Error message :
The following construct was used in query but is not recognised by the
F#-to-LINQ query translator: Call
(None,
System.Collections.Generic.IEnumerable1[System.Tuple2[System.DateTime,System.String]]
Singleton[Tuple2](System.Tuple2[System.DateTime,System.String]),
[NewTuple (PropertyGet (Some (a), System.DateTime Date, []),
PropertyGet (Some (d), System.String AboveMessage,
[]))]) This is not a valid query
expression. Check the specification of
permitted queries and consider moving
some of the query out of the quotation
Fixed
Code :
let px =
query <|
<# seq { for cl in db.Dictionaries -> cl }
|> Seq.filter(fun x -> x.ID_Line = l1 || x.ID_Line = l2) #>
|> fun pquery ->
query <|
<# seq { for cd in db.DeltaCompares do
for cl1 in pquery do
if cd.IID1 = cl1.IID then
for cl2 in pquery do
if cd.IID2 = cl2.IID then
yield cl1
yield cl2 } #>
|> List.ofSeq
Same error with update :
let p =
[for cl in db.Dictionaries -> cl]
|> Seq.filter(fun x -> x.ID_Line = l1 || x.ID_Line = l2)
|> fun pquery ->
<# seq { for cd in db.DeltaCompares do
for cl1 in pquery do
for cl2 in pquery do
if cd.IID1 = cl1.IID && cd.IID2 = cl2.IID then
yield cl1, cl2 } #>
|> query |> Seq.collect(fun a -> [fst a; snd a])
Error message :
The following construct was used in query but is not
recognised by the F#-to-LINQ query
translator: Call (None,
System.Collections.Generic.IEnumerable`1[LinqBase.Dictionary]
SingletonDictionary,
[cl1]) This is not a valid query expression. Check the specification of
permitted queries and consider moving
some of the query out of the quotation
fixed
I'm not sure if I do it correct so I also ask you to confirm if this is a bug or not a bug
In the first case, I think the F#-to-LINQ translator may be failing on nested if. Have you tried: (...)
EDIT [Second attempt]: It could also fail because we're using if without else clause. What if you always return something using option type and then filter out None values (there may be a way to make it nicer, but let's start with this):
<# seq {for a in db.ArchiveAnalogs do
for d in db.Deltas do
yield
if a.ID = d.ID && a.Value > d.DeltaLimit then
Some(a.Date, d.AboveMessage)
elif a.ID = d.ID a.Value < d.DeltaLimit then
Some(a.Date, d.BelowMessage)
else None }
#> |> query |> Seq.choose id |> Array.ofSeq
In the second case, it may be failing because of the for nested in if. I'd try this (...)
EDIT: This is actually incorrect use of LINQ (and it wouldn't work in C# too). The problem is that you're collecting some data in memory (pquery) and then passing this as an input to the LINQ (so that it would have to send the data back to the SQL server.
You can try writing it like this (BTW: I think using |> fun x -> is a weird construct when you can write the same thing simply just using let):
let pquery = <# db.Dictionaries
|> Seq.filter(fun x -> x.ID_Line = l1 || x.ID_Line = l2) #>
let px =
<# seq { for cd in db.DeltaCompares do
for p in %pquery do ... } |> query
This is using quotation splicing. For more information about this feature, see my article (search for splicing).