Reputation: 15
I have a simple program written in Scala, which operates logical expressions as members of the case classes, which extend Expr trait (code below). Then I have some functions that simply pattern match on the class of the argument and perform some actions.
sealed trait Expr
case class Implication(lhs: Expr, rhs: Expr) extends Expr {
override def toString = "(" + lhs.toString + "->" + rhs.toString + ")"
}
case class Negation(body: Expr) extends Expr {
override def toString = "!" + body.toString
}
case class Conj(lhs: Expr, rhs: Expr) extends Expr {
override def toString = "(" + lhs.toString + "&" + rhs.toString + ")"
}
case class Disj(lhs: Expr, rhs: Expr) extends Expr {
override def toString = "(" + lhs.toString + "|" + rhs.toString + ")"
}
case class Variable(name: String) extends Expr {
override def toString = name
}
Example of a function:
def substitute(map: m.HashMap[String, Expr]): Expr = this match {
case Variable(name) => map.getOrElse(name, this)
case Conj(a, b) => Conj(a.substitute(map), b.substitute(map))
case Disj(a, b) => Disj(a.substitute(map), b.substitute(map))
case Implication(a, b) => Implication(a.substitute(map), b.substitute(map))
case Negation(a) => Negation(a.substitute(map))
}
The question is: How can I imitate the same functionality in Clojure? Basically all I want is to distinguish the class of a function argument and pattern match on it, preferably with guards.
Upvotes: 0
Views: 466
Reputation: 3951
The problem can be solved using if
, cond
, condp
or other conditional operators. To find class use class
or type
functions.
Use zippers to walk and edit map tree. http://ravi.pckl.me/short/functional-xml-editing-using-zippers-in-clojure/
There are many ways to tag entries in map:
Take a look at enlive for inspiration - https://github.com/cgrand/enlive
Upvotes: 0
Reputation: 181
It looks like the core of an expression is that it is a recursive data structure with tagged nodes. You could build the expression data structure from an example of a Red-Black tree in Clojure.
The key insight is that the expression tree is represented with nested plain Clojure datatypes. In the red-black example, each node is a 4-tuple [type left-child value right-child]. In your example, it might make more sense to represent an expression as [type & children].
In either case, core.match uses pattern matching against plain Clojure types like vectors and keywords. You could probably port your expression match 1-to-1.
Upvotes: 0