Ah, other engines
don't do nested accessors because they're wimps. WIMPS!
:)
I'd like to see a situation where we have the convenience of nested
accessors, but mapping to fully relational joins. This is combine
with some nice XPATH like syntax too.
Implicit mapping I call Managed Object Graphs MOGs. So you can write
Person( address.street == "my road" )
And that internally would get translated too
$p : Person()
Address( person == $p, street == "my road" )
As there is no doubt that the current explicit bindings approach on
objects is too verbose and hard to read. Nested accessors add a lot
of readability.
I also want to add xpath like syntax as a short cut for 'from', as I
think it makes for easier readability:
Bookshop()/books( author == "some author" )
Which is a short cut for:
$b : Bookshop
Book( author == "some author" ) from $b.books
And would support map/list access like xpath:
Person()/pets[0]/( age > 30)
Whichis short for
$p : Person()
Pet( owner == $p, age > 30 ) from $p.pets[0]
Again if the nested objects are inserted as MOGs, the joins would be
obeyed instead of using 'from', i.e. they'll receive notifications
from nested object update.
This is partly why I think we need to have a think about syntax
accessors in general, before we decide what to do, there are a lot
of related areas and a decision in one area impacts another.
Yes, that is exactly what I think. Pattern
matching constraints are like query parameters. They
need to exist and evaluate to true in order to
match. So, for this to match:
a.b.c == null
a needs to exist and be non-null, b needs
to exist and be non-null, c needs to exist and
be null. So it is not just NP safe navigation...
it is an existence test at the same time. So for
maps
a[x].b[y].c[z] == null
The keys x, y and z need to exist, and
c[z] must have a value of null. That is what the
expression above is asking for, in my
understanding.
This presents no loss of completeness to
the language, as you can still test
non-existence of keys if that is what you want,
but the most common case you are looking for the
opposite and it becomes much simpler to write
rules that way.
> So, a builder option to turn this on is
allright with me.
We can probably do that and have a
configuration option to turn this feature
on/off.
I'm strongly against configuration options in this
case, we decide on one way and stick with it. We
already have too many configurations and a casual
person looking at the code could introduce a bug as
they weren't aware of what configuratino was on for
null safety.
I think part of the problem here is we are mixing
domains, between script evaluation and relational
constraints. There is a reason why other rule engines
don't do nested accessors :) (ignoring the technical
issues too).
I think we need to
differentiate paradigms here. When
using rules, contrary to
imperative code, what we are doing
is pattern matching.
X( a.b.c == <value> )
In the above case, we are
looking for Xs that make that
whole constraint true (i.e.
match). If a or b are null, the
whole expression will be false,
does not matter the value of c or
the value it is being compared
against.
(Edson: Only if you define it so.
The logical implication of c being
null in an absent a.b (i.e.,
a.b==null) could very well be that
"a.b.c does not exist", and you
can't claim that a.b.c exists if
a.b. doesn't!
Is there no house at some address?
(city.street[name].house[number]
== null) # true => no such house
$c : City()
$s : Street( city == $c, street = "name" )
House( number == null)
The above is identical logic to the more
convenient form of nested accessors, it's
the proper relational form. In this case if
there was no Street, it wouldn't match.
This test data with false when
null: Vienna/TirelliStrasse/42
returns "false", hence there is
such a house. But we don't have a
Tirelli Street in Vienna (yet)!
Confer this to Perl's
! exists
$city{-streets}{"Tirelli"}[42]
)
Raising a null pointer
exception, IMO, brings no
advantage at all to the table...
on the contrary, makes writing
rules more difficult.
Edson, Mark,... please do recall
the times where you have had an
NPE in the code in a boolean
expression? How painful would it
have been if Java would have
returned "false", continuing to
cover a coding error made
elsewhere?
Why don't other languages tolerate
"null" silently? (Perl, the most
pragmatic of all, doesn't - it has
introduced an operator I can use
or not.)
I have no problem when folks want
to take shortcuts and live la
dolce vita, but
<em>I don't want to be led
into the bog without my
consent.</em>
So, a builder option to turn this
on is allright with me.
Another example we had in
the past:
class Circle implements Shape
class Square implements Shape
rule X
when
Circle() from $shapes
...
In the above example,
$shapes is a list and the rule
is clearly looking for Circles.
If there are Squares in there,
they will just not match.
Raising a ClassCastException
like it would happen in an
imperative language brings no
advantage to the table, IMO.
This is an entirely different
matter than the previous one. I
see no reason whatsoever, not to
define this "from" as working with
an implicit filter.
-W
So, IMO, all property
navigation should be null
pointer safe in the LHS of the
rules.
This is not what happens
today, but I think it should be
fixed.
I agree with W. : NPE
should be the default, and
"null" cases behaviour
should be planned by
programmers.
But I am not sure about
using a new operator in
rules (and do the update
in Guvnor ...).
Why not using some drools
annotations on the getter
specifying the behaviour
of an eval on a null value
returned by this getter ?
And may be these
annotation could be added
to an existing POJO via
the declared type syntax
(just like event role in
fusion) ?