Fork me on GitHub
#clara
<
2018-10-25
>
eraserhd13:10:46

@souenzzo wait, really? Is there a list of functions that Clara handles specially?

eraserhd13:10:02

I mean, knows how to join, other than =?

souenzzo13:10:15

I use = and contanis?. I learned it when I did not understand how clara works then never search for it.

jvtrigueros13:10:00

As a newcomer it’s not super clear which functions are built-in. This is definitely an advanced user library :)

ethanc14:10:04

I'm believe that the only functions that Clara handles specially are the equality expressions: https://github.com/cerner/clara-rules/blob/master/src/main/clojure/clara/rules/compiler.clj#L213-L223

mikerod14:10:54

Yeah, = is the only special thing

mikerod14:10:17

It still means = too, but it can also be used for unification purposes/binding variables

mikerod14:10:47

nothing is special about contains? (or anything else)

wparker14:10:16

Agreed with other comments that it is just = that is special when used as a top-level value in the constraint to create/join on bindings (starting with ?)

wparker14:10:40

that has perf benefits in that those joins are done by hashing

wparker14:10:12

otherwise you can use arbitrary functions and they should behave the same as elsewhere

jvtrigueros14:10:46

While reading the docs, it goes from straightforward to advanced very quickly. In http://www.clara-rules.org/docs/rules/, I fully understand the free-lunch-with-gizmo because there's no ? binding, you're matching that an item is :gizmo, but then in the sophisticated example:

(defrule grant-discount-months  
  [Purchase (= ?month (get-month date))]
  [DiscountMonth (= ?month month)]
  =>
  (insert! (->GrantDiscount :for-month ?month)))
The = doesn't have the same meaning (in the Purchase condition) as the straightforward example, but it does in the DiscountMonth condition?

wparker14:10:11

it has the same meaning in that it requires equality, but clojure.core/= won’t be called

eraserhd14:10:16

= is unification. So, it requires the expression to be true. If there are variables in it that do not yet have a value, the variables are "assigned" such to make it true. If the variables are already assigned, it works like clojure.core/=

mikerod14:10:31

That’s a reasonable way to think about it

mikerod14:10:36

but Clara may optimize on it

mikerod14:10:49

when unifying on a ? binding

mikerod14:10:58

it uses it to build the rete graph

jvtrigueros14:10:20

> = is unification This distinction is makes sense!

mikerod14:10:23

makes a hash-based match for nodes known to be doing = based bindings

mikerod14:10:36

but = is also just = when equating to constant values etc

eraserhd14:10:36

If there are many possible values for a variable, it can assign each value consecutively.

mikerod14:10:53

you can do [Purchase (= ?month month "JAN")] for example

eraserhd14:10:55

(*and what @mikerod is saying is true, I'm only describing the semantics, it doesn't actually work like that.)

mikerod15:10:05

yeah, semantics are most important

mikerod15:10:25

just making sure someone may not get carried away and try to print within clojure.core/= or something and wonder why it isn’t always called hah

mikerod15:10:15

[Purchase (= ?month month "JAN")] binds the value of the field month to ?month, when (= month "JAN") (via clojure.core/=)

mikerod15:10:25

Of course in this case, ?month would just be “JAN”

mikerod15:10:51

so perhaps something a bit more useful than that 😛

wparker15:10:25

This page on the docs might be of interest: http://www.clara-rules.org/docs/hash_joins/

jvtrigueros15:10:10

Woah secret docs

wparker15:10:14

“`=` is unification” => correct. Note that this is for top-level constraints though, when nested inside a constraint that isn’t the case i.e. [A (= ?b c)] vs [A (stuff (= ?b c))]

wparker15:10:46

Hah not secret, just nested inside the “performance optimization” page

wparker15:10:27

Or more precisely on my last, that is true if you’re trying to create new bindings - it’s still unification semantically if you’re using bindings from before

jvtrigueros15:10:17

> [A (= ?b c)] vs [A (stuff (= ?b c))] Yes! This is what I ran into immediately, I wanted to use my own equality function, but I got pointed to using :test instead.

jvtrigueros15:10:15

BTW thank you all for helping me understand this!

mikerod15:10:17

some of the semantics around = can get weird, since it kind of plays 2 roles depending on context

mikerod15:10:27

like when how you can’t nest it within another call to do a unification

mikerod15:10:38

but most of the time not a big deal

jvtrigueros22:10:32

Is it possible to transform the output of defquery or would I need to do that in a wrapper function? The RHS of a defrule is just Clojure but that doesn't seem to exist in defquerys

mikerod22:10:40

@jvtrigueros defquery has no RHS

mikerod22:10:11

you can create facts in rules with defrule that do some transformations so there is less to transform once you get it from the query

mikerod22:10:28

but the query return val will just be the maps with the binding keys to the values they are bound to in the query

jvtrigueros22:10:06

Thanks! In the query docs, it suggests one can write a query like so:

(query session get-by-last-name :last-name “Jones”)
How would one write the defquery for that?
(defquery get-by-last-name
  [:last-name]
  [?person <- Person (= last-name :last-name)])

jvtrigueros22:10:00

I'm only able to create defquerys that have ?:

(defquery get-by-last-name
  [:?last-name]
  [?person <- Person (= last-name ?last-name)])
But then the query call wouldn't be using :last-name but :?last-name