I have a function that accepts a single argument that is described by the following grammar:
term := (Less | Greater | Equal | LessEqual | GreaterEqual)[Symbol,Number]
argument := term | Or[term,term,...]
The expressions are generated from operations like:
Reduce[x^2 -x -6x == 0, x, Reals] // FullForm
(* Or[Equal[x,-2],Equal[x,3]] *)
I want to use a pattern in the function definition to ensure that the argument is of the correct form and I want to convert the argument into the following form for use within the function:
List[term,...]
I am currently bogged down in pattern purgatory. I have tried all of the following and am confused by the results.
(* Test data *)
s = Or[Equal[x,-2],GreaterEqual[x,3]]
This pattern matched the test case. So far so good.
(* case 1 *)
s /. Or[(Less | Greater | Equal | LessEqual | GreaterEqual)
[x_Symbol, (_Integer | _Rational | _Real)] ..] :> {2}
(* {2} V {2} *)
Let's see if we can capture the head in a variable. Yes, we can. I've got this figured out.
(* case 2 *)
s /. f_Symbol[(Less | Greater | Equal | LessEqual | GreaterEqual)
[x_Symbol, (_Integer | _Rational | _Real)] ..] :> {f}
(* {Or} *)
Let's limit the pattern to a specific head instead of any symbol. This didn't match. I'm not clear on why.
(* case 3 *)
s /. f_Or[(Less | Greater | Equal | LessEqual | GreaterEqual)
[x_Symbol, (_Integer | _Rational | _Real)] ..] :> {f}
(* No Match *)
Maybe a different syntax will work. And it does, but I expected {Or}
as a result.
(* case 4 *)
s /. f : (Or)[(Less | Greater | Equal | LessEqual | GreaterEqual)
[x_Symbol, (_Integer | _Rational | _Real)] ..] :> {f}
(* {x == -2} V {x >= 3} *)
Edit: Some appropriately placed parens make a difference. I understand this result, but I still don't understand the previous one.
(* case 5)
s /. (f : Or)[(Less | Greater | Equal | LessEqual | GreaterEqual)
[x_Symbol, (_Integer | _Rational | _Real)] ..] :> {f}
(* {Or} *)
End Edit
I am missing something important about how patterns/rules work. I would like to correct that gap in knowledge. And, secondarily, I'd like to get my function to only accept an appropriate argument and be able to convert the argument into the desired format.
f_Or
won't matchOr[f]
because it is already evaluated and becomesf
$\endgroup$f_Or
matches something with headOr
, not exactlyOr
. So,_Or[stuff]
matchesOr[something][stuff]
$\endgroup$Symbol
is a symbol, andOr
is another symbol. One isn't a subset of the other. All symbols have the "invisible head"Symbol
. With that in mind,Or
matches_Symbol
.f_Or
would be "equivalent" tof:Or[___]
which would be a subset off:_Symbol[___]
$\endgroup$