I assume that I can pass in arbitrary values and don't need to convert them to some Yeti wrapper, or? Do I get a ClassCastException if they don't typecheck?
Not exactly - Yeti strings are java.lang.String and booleans java.lang.Boolean, but other datatypes use Yeti wrappers. Numbers are instances of abstract yeti.lang.Num (which has subclasses IntNum?, BigNum, RatNum?, FloatNum?), lists yeti.lang.AList (usual linked list is LList), arrays yeti.lang.MList (as mutable list), hashes yeti.lang.Hash (which extends java.util.HashMap), structures yeti.lang.Struct and tagged values yeti.lang.Tag. The compiler does most sensible conversions by itself, when calling Java from Yeti, but when calling Yeti from Java you'll have to do it by hand. ClassCastExceptions will happen when wrong types of values are given from Java code.
You should provide a facade for converting Java types into the corresponding Yeti types (and back). Such that it is possible to write io.println.apply(Yeti.from(42)) or int x = Yeti.toInt(my.code.f(Yeti(42))). This would make Yeti more usable as a small language in a larger Java project.
Seems good idea. Currently it is possible to somewhat simplify the calling by declaring Yeti function as getting value of some Java class as argument, like import some.weird.Thing; f x is ~Thing -> string = x#toString(). Problem is that too much Java calls mixed into Yeti looks somewhat like a mess (or at least not like a nice Yeti code).
Solved it actually in an another way - by adding a way to define normal Java classes in the Yeti code (http://linux.ee/~mzz/yeti/intro.html#public-classes). This way the compiler can mostly take care of these conversions. Additionally some smart automatic casting has been added to keep Java calls nicer in the Yeti code. :)