Clojure case statement with classes - class

I want to switch on the class of a given object in order to encode it.
(defn encoded-msg-for [msg]
(case (class msg)
java.lang.Double (encode-double msg)
java.lang.String (encode-str msg)
java.lang.Long (encode-int msg)
java.lang.Boolean (encode-bool msg)
clojure.lang.PersistentArrayMap (encode-hash msg)
clojure.lang.PersistentVector (encode-vec msg)
nil "~"
)
)
When I call (encoded-msg-for {}), it returns No matching clause: class clojure.lang.PersistentArrayMap
What is odd is that putting the cases into a hash-map (with the classes as keys and strings as values) works perfectly well.
Also, (= (class {}) clojure.lang.PersistentArrayMap) is true. What comparison is happening here and how can I switch either on the class of the object itself or (better) something in its hierarchy?

I believe case treats the class names as literal symbols - it does not resolve them to actual classes:
>>> (case 'clojure.lang.PersistentArrayMap clojure.lang.PersistentArrayMap 1 17)
1
>>> (case clojure.lang.PersistentArrayMap clojure.lang.PersistentArrayMap 1 17)
17
This is rather unintuitive, but so it works in Clojure's case. Anyway, the idiomatic way is to use defmulti and defmethod instead of switching on type:
(defmulti encoded-msg class)
(defmethod encoded-msg java.util.Map [x] 5)
(defmethod encoded-msg java.lang.Double [x] 7)
>>> (encoded-msg {})
5
>>> (encoded-msg 2.0)
7
The dispatcher uses the isa? predicate which deals well with the comparisons of types, in particular it works well with Java inheritance.
If you don't want to use defmulti, then condp might replace case in your use case, as it properly evaluates the test-expressions. On the other hand it doesn't provide constant time dispatch.

If you are dispatching only on the class then protocols might be a nice solution, because they will enable you (or your API's client) to provide implementations for other types at a later time, here is an example:
(defprotocol Encodable
(encode [this]))
(extend-protocol Encodable
java.lang.String
(encode [this] (println "encoding string"))
clojure.lang.PersistentVector
(encode [this] (println "encoding vector")))
If you need to have finer-grained dispatch or you know extending to other types is not necessary then there might be too much boilerplate in this solution.

If you are looking for an alternative way to achieve this, take a peek at condp:
(condp = (type {})
clojure.lang.PersistentArrayMap :one
clojure.lang.PersistentVector :many
:unknown) ;; => :one

Related

Custom control structure with two blocks

I'm entirely new to Scala and while reading some tutorials and documentation, I experimented with defining custom control structures.
So I tried to implement an implicit class MyBoolean that provides a ? method with two parameter lists. The first parameter is a block that gets executed if MyBoolean is true, the second gets executed if MyBoolean is false.
Here is an example of how the syntax of the resulting control structure should look like:
true ? {println("true")} {println("false")};
so essentially just a simple if-else statement implemented as a method on Boolean.
Here is my implementation:
object Test extends App {
implicit class MyBoolean(val value: Boolean) {
def ? (body1: => Unit)(body2: => Unit){
if (value) body1;
else body2
}
}
override def main(args: Array[String]): Unit = {
// true ? {println("true")} {println("false")}; //--> compiler error
true.? {println("true")} {println("false")}; // works fine...
}
}
The problem I'm facing is that I get the following compiler error with the intended syntax (in Eclipse):
missing arguments for method ? in class MyBoolean; follow this method
with `_' if you want to treat it as a partially applied function
It only works if I explicitly add the dot . before the method ?.
Shouldn't the dot be optional in Scala when calling methods? Is there anything I'm missing?
Shouldn't the dot be optional in Scala when calling methods?
Sort of, but that's not exactly accurate.
In these cases, that's true:
a.b(c) can be written as a b c
a.b(c, d) can be rewritten as a b (c, d).
From the language spec section 6.12.3, Infix Operations:
The right-hand operand of a left-associative operator may consist of several arguments enclosed in parentheses, e.g. e op e1, …, en. This expression is the interpreted as e.op(e1, …, en).
A left-associative binary operation e1 op e2 is interpreted as e1.op(e2).
But there is no corresponding rule for expressions of the form a.b(c)(d). I'm not really sure why, though. It seems to me that a b {c} {d} would be a perfectly reasonable way to write that.
This is one of the weirdest wrinkles in Scala syntax. You can still use point-free style with multiple argument lists but you have to group the object, method, and first argument list using parentheses (?!)
(true ? {println("true")}) {println("false")}
works just fine.
Why does it work this way? It is rather convenient with the /: and :\ fold symbols; then you can group your first element together with the collection it's supposed to run through.
For everything else it is questionable at best.
Regardless, you're stuck with either parentheses or a dot.
The dot's optional when calling 1-parameter methods, but that syntax doesn't work for a 2-parameter method, even when curried (except as #RexKerr suggests if you bracket it).
You might be able to get it working by doing "manual" currying: write a one-parameter method that returns an object with an apply:
class PartiallyApplied(value: Boolean, body1: => Unit) {
def apply(body2: => Unit) = if (value) body1; else body2
}
class MyBoolean...
def ? (body1: => Unit) = new PartiallyApplied(value, body1)

clojure - extending types in non-vanilla ways

I'm new to Clojure.
In Java I can do something like this extremely contrived example:
public abstract class Foo {
public void sayHello(String name) {
System.out.println("Hello, " + name + "!");
}
}
public interface Fooable {
public void sayHello(String name);
}
public class Bar extends Foo implements Fooable, Barable {
...
}
public class Baz extends Foo implements Fooable, Barable {
...
}
So, here we have two classes, implementing the Fooable interface the same way (through their abstract base class parent) and (presumably) implementing the Barable interface two different ways.
In Clojure, I can use defrecord to define types Bar and Baz, and have them implement protocols rather than interfaces (which, essentially, are what protocols are, from what I understand). I know how to do this in the most basic sense, but anything more complex is stumping me.
Given this:
(defrecord Bar [x])
(defrecord Baz [x y])
(defprotocol Foo (say-hello [this name]))
how would I recreate the abstract base class functionality above, i.e. have one protocol implemented the same way across multiple defrecord types, without duplicating code? I could of course do this, but the code repetition makes me cringe:
(extend-type Bar
Foo
(say-hello [this name] (str "Hello, " name "!")))
(extend-type Baz
Foo
(say-hello [this name] (str "Hello, " name "!")))
There has to be a cleaner way of doing this. Again, I'm new to Clojure (and Lisp in general; I'm trying to learn Common Lisp concurrently), so macros are an entirely new paradigm for me, but I thought I'd try my hand at one. Not surprisingly, it fails, and I'm not sure why:
(defmacro extend-type-list [tlist proto fmap]
(doseq
[t tlist] (list 'extend t proto fmap)))
fmap of course is a map of functions, i.e. {:say-hello (fn [item x] (str "Hello, " x "!"))} The doseq, applied to a concrete list of record types and a concrete protocol, does work. Within the macro, of course, it doesn't, macroexpand calls return nil.
So, question 1, I guess, is "what's wrong with my macro?". Question 2 is, how else can I programmatically extend protocols for types without a lot of repetitive boilerplate code?
Your macro is returning nil because doseq returns nil.
A Clojure macro should generate a new form using a combination of syntax-quotes (`), unquotes (~), and unquote-splicing (~#) reader macros.
(defmacro extend-type-list [types protocol fmap]
`(do ~#(map (fn [t]
`(extend ~t ~protocol ~fmap))
types)))
Without using a macro, you have a few options:
(defrecord Bar [x])
(defrecord Baz [x y])
Use a simple var to hold the function map:
(defprotocol Foo (say-hello [this name]))
(def base-implementation
{:say-hello (fn [this name] (str "Hello, " name "!"))})
(extend Bar
Foo
base-implementation)
(extend Baz
Foo
base-implementation)
(say-hello (Bar. 1) "Bar") ;; => "Hello, Bar!"
(say-hello (Baz. 1 2) "Baz") ;; => "Hello, Baz!"
If you move to multimethods, you can accomplish something similar with clojure.core/derive
(defmulti say-hello (fn [this name] (class this)))
(derive Bar ::base)
(derive Baz ::base)
(defmethod say-hello ::base [_ name]
(str "Hello, " name "!"))
(say-hello (Bar. 1) "Bar") ;; => "Hello, Bar!"
(say-hello (Baz. 1 2) "Baz") ;; => "Hello, Baz!"
Question 1
Macros are just normal functions that are called at compile-time rather than run-time. If you look at the definition of defmacro, it actually just defines a function with some special meta-data.
Macros return Clojure syntax, which is spliced into the code at the point of the macro call. This means that your macro should return (quoted) syntax that looks exactly like what you would have typed manually into the source file at that point.
I find that a good way to design complex macros is to first declare it with defn, tweaking it until it returns my expected output. As with all Lisp development, the REPL is your friend! This approach requires you to manually quote any parameters being passed to your proto-macro function. If you declare it as a macro then all the arguments are treated as data (e.g. variable names are passed in as symbols), but if you call it as a function it'll try to actually evaluate the arguments if you don't quote them!
If you try this out with your macro you'll see that it doesn't actually return anything! This is because you're using doseq, which is for side-effecting computations. You want to use for in order to build up the syntax to do all of the extend-type calls. You'll probably need to wrap them in a (do ) form since a macro must return a single form.
Question 2
According to the documentation, you can actually implement multiple interfaces/protocols directly within inside the defrecord macro. After your field declaration, just add the bodies of all the extend-type forms you would have declared.
(defrecord Bar [x]
Foo1
(method1 [this y] 'do-something)
Foo2
(method2 [this y z] 'do-something-else))
It looks like the two questions you asked at the bottom have been pretty comprehensively answered, but you asked something interesting in the text of the question: "how would I recreate the abstract base class functionality above, i.e. have one protocol implemented the same way across multiple defrecord types, without duplicating code?"
If we look at the documentation for datatypes, two quotes jump out:
Concrete derivation is bad
you cannot derive datatypes from concrete classes, only interfaces
Tying polymorphism to inheritance is bad
Clojure datatypes intentionally restrict some features of Java, for example concrete derivation. So I believe the answer to your question really is, "you shouldn't". Multimethods or def'ing the functionality outside the defrecord and calling into it (like DaoWen's answer) should be preferred.
But if you really, really want to do exactly what you're doing in Java, you can use gen-class to extend a class.
(gen-class :name Bar :extends Foo :implements [Fooable])
(gen-class :name Baz :extends Foo :implements [Fooable])
Note that this implementation is a bit of a hack (you can't test in the repl because gen-class only does something when compiling), and doesn't use the :gen-class key in the ns macro like you typically would if you really had to gen-class. But using gen-class at all is a bit of a hack.

Pattern matching on List[T] and Set[T] in Scala vs. Haskell: effects of type erasure

Would the Haskell equivalent of the code below produce correct answers?
Can this Scala code be fixed to produce correct answers ? If yes, how ?
object TypeErasurePatternMatchQuestion extends App {
val li=List(1,2,3)
val ls=List("1","2","3")
val si=Set(1,2,3)
val ss=Set("1","2","3")
def whatIsIt(o:Any)=o match{
case o:List[Int] => "List[Int]"
case o:List[String] => "List[String]"
case o:Set[Int] => "Set[Int]"
case o:Set[String] => "Set[String]"
}
println(whatIsIt(li))
println(whatIsIt(ls))
println(whatIsIt(si))
println(whatIsIt(ss))
}
prints:
List[Int]
List[Int]
Set[Int]
Set[Int]
but I would expect it to print:
List[Int]
List[String]
Set[Int]
Set[String]
You must understand that by saying o:Any you erase all the specific information about the type and further on the type Any is all that the compiler knows about value o. That's why from that point on you can only rely on the runtime information about the type.
The case-expressions like case o:List[Int] are resolved using the JVM's special instanceof runtime mechanism. However the buggy behaviour you experience is caused by this mechanism only taking the first-rank type into account (the List in List[Int]) and ignoring the parameters (the Int in List[Int]). That's why it treats List[Int] as equal to List[String]. This issue is known as "Generics Erasure".
Haskell on the other hand performs a complete type erasure, which is well explained in the answer by Ben.
So the problem in both languages is the same: we need to provide a runtime information about the type and its parameters.
In Scala you can achieve that using the "reflection" library, which resolves that information implicitly:
import reflect.runtime.{universe => ru}
def whatIsIt[T](o : T)(implicit t : ru.TypeTag[T]) =
if( t.tpe <:< ru.typeOf[List[Int]] )
"List[Int]"
else if ( t.tpe <:< ru.typeOf[List[String]] )
"List[String]"
else if ( t.tpe <:< ru.typeOf[Set[Int]] )
"Set[Int]"
else if ( t.tpe <:< ru.typeOf[Set[String]] )
"Set[String]"
else sys.error("Unexpected type")
println(whatIsIt(List("1","2","3")))
println(whatIsIt(Set("1","2","3")))
Output:
List[String]
Set[String]
Haskell has a very different approach to polymorphism. Above all, it does not have subtype polymorphism (it's not a weakness though), that's why the type-switching pattern matches as in your example are simply irrelevant. However it is possible to translate the Scala solution from above into Haskell quite closely:
{-# LANGUAGE MultiWayIf, ScopedTypeVariables #-}
import Data.Dynamic
import Data.Set
whatIsIt :: Dynamic -> String
whatIsIt a =
if | Just (_ :: [Int]) <- fromDynamic a -> "[Int]"
| Just (_ :: [String]) <- fromDynamic a -> "[String]"
| Just (_ :: Set Int) <- fromDynamic a -> "Set Int"
| Just (_ :: Set String) <- fromDynamic a -> "Set String"
| otherwise -> error "Unexpected type"
main = do
putStrLn $ whatIsIt $ toDyn ([1, 2, 3] :: [Int])
putStrLn $ whatIsIt $ toDyn (["1", "2", "3"] :: [String])
putStrLn $ whatIsIt $ toDyn (Data.Set.fromList ["1", "2", "3"] :: Set String)
Output:
[Int]
[String]
Set String
However I must outline boldly that this is far from a typical scenario of Haskell programming. The language's type-system is powerful enough to solve extremely intricate problems while maintaining all the type-level information (and safety). Dynamic is only used in very special cases in low-level libraries.
GHC does even more type erasure than the JVM; at runtime the types are completely gone (not just the type parameters).
Haskell's approach to types is to use them at compile time to guarantee that no ill-typed operation can ever be carried out, and since Haskell doesn't have OO-style subtyping and dynamic dispatch, there's no purpose at all to keeping the types around. So data is compiled to a memory structure that simply contains the right values, and functions are compiled with baked-in knowledge of the structure of the types on which they operate1, and just blindly expect their arguments to have that structure. That's why you get fun things like segmentation faults if you mess with unsafeCoerce incorrectly, not just a runtime exception saying the value was not of the expected type; at runtime Haskell has no idea whether a value is of any given type.
So rather than Haskell giving "the right answer" to the equivalent program, Haskell disallows your program as unsafe! There is no Any type in Haskell to which you can cast whatever you want.
That's not 100% true; in both Haskell and Scala there are ways of keeping type information alive at runtime. Essentially it's done by creating ordinary data structures that represent types, and passing them around together values that are of those types, so at runtime you can refer to the type representation object for information about the type of the other object. There are library and language facilities in both languages to let you use this mechanism at a higher (and more principled) level, so that it's easier to use safely. Because it requires the type tokens to be passed around, you have to "opt-in" to such features, and your callers have to be aware of it to pass you the required type tokens (whether the actual generation and passing of the token is done implicitly or explicitly).
Without using such features, Haskell provides no way to pattern match on a value that could be of type List Int or Set String to find out which one it is. Either you're using a monomorphic type, in which case it can only be one type and the others will be rejected, or you're using a polymorphic type, in which case you can only apply code to it that will do the same thing2 regardless of which concrete type instantiates the polymorphic type.
1 Except for polymorphic functions, which assume nothing about their polymorphic arguments, and so can basically do nothing with them except pass them to other polymorphic functions (with matching type class constraints, if any).
2 Type class constrained polymorphic types are the only exception to this. Even then, if you've got a value a type that's a member of some type class, all you can do with it is pass it to other functions that accept values in any type that is a member of that type class. And if those functions are general functions defined outside of the type class in question, they'll be under the same restriction. It's only the type class methods themselves that can actually "do something different" for different types in the class, and that's because they are the union of a whole bunch of monomorphic definitions that operate on one particular type in the class. You can't write code that gets to take a polymorphic value, inspect it to see what it was instantiated with, and then decide what to do.
Of course Haskell prints the right answer:
import Data.Set
import Data.Typeable
main = do
let li=[1,2,3]
let ls=["1","2","3"]
let si=Data.Set.fromList[1,2,3]
let ss=Data.Set.fromList["1","2","3"]
print $ typeOf li
print $ typeOf ls
print $ typeOf si
print $ typeOf ss
prints
[Integer]
[[Char]]
Set Integer
Set [Char]

Clojure: def discards ^:macro when used outside the top-level

If I evaluate
(def ^:macro my-defn1 #'defn)
a macro named 'my-defn1' is defined, which I can use just like 'defn'.
However, if I evaluate instead
(if true
(def ^:macro my-defn2 #'defn))
the var for 'my-defn2' doesn't have the :macro metadata set and I can't use it as a macro, even though the 'def' form is equal to the previous case.
Here is the complete code (http://cljbin.com/paste/52322ba5e4b0fa645e7f9243):
(def ^:macro my-defn1 #'defn)
(if true
(def ^:macro my-defn2 #'defn))
(println (meta #'my-defn1)) ; => contains :macro
(println (meta #'my-defn2)) ; => doesn't contain :macro!
(my-defn1 hello1 []
(println "hello 1"))
(hello1) ; => prints "hello 1"
(my-defn2 hello2 [] ; => CompilerException: Unable to resolve
(println "hello 2")) ; symbol: hello2 in this context
What makes the behaviour different?
Clojure's def cannot really be conditionally applied. The documentation for def is IMO insufficiently strong on that part. It's not just bad style, it can cause all kinds of subtle issues.
You should only use def at the top-level, or in a do or let form at the top-level. Conditionally applying def will result in the functionality being split up in something like declare and a subsequent conditional def, but not always in the way that you'd expect/like.
You might be better off using def at the top level here and then conditionally using alter-var-root. Or use (def my-var (if .. .. ..)). Think about why you'd ever want to have a global definition "disappear".

Is it possible to implement `??` (a null coalescing operator from C#) in Scala that does not use reflection?

I've found somewhere an implementation of C# null coalescing operator '??':
implicit def coalescingOperator[T](pred: T) = new {
def ??[A >: T](alt: =>A) = if (pred == null) alt else pred
}
It can be then used like a ?? b which means if (a == null) b else a.
And after decompiling the class files I saw that it produces code with reflection (in Scala 2.8.1).
Why it generates reflection and is it possible to modify that code so it would not generate reflection?
Scala doesn't have the same idea of anonymous classes as Java does. If you say something like
new {
def fish = "Tuna"
}
then it will interpret all uses of the new method as requiring a structural type, i.e. the same as
def[T <: {def fish: String}](t: T) = t.fish
which needs to use reflection since there's no common superclass. I don't know why it's this way; it's exactly the wrong thing to do for performance, and usually isn't what you need.
Regardless, the fix is easy: create an actual class, not an anonymous one.
class NullCoalescer[T](pred: T) {
def ??[A >: T](alt: => A) = if (pred == null) alt else pred
}
implicit def anyoneCanCoalesce[T](pred: T) = new NullCoalescer(pred)
In 2.10, it still does the arguably wrong thing, but (1) it will throw warnings at you for using reflection this way (so at least you'll know when it's happened) unless you turn them off, and (2) you can use a shorter version implicit class /* blah blah */ and skip the implicit def which just adds boilerplate.