crystal lang : in case of a Class as a field - crystal-lang

I'm just writting an Exception, which should stores a Class object as a field for the error message process.
class BadType < Exception
getter should_be : Class
getter actual : Class
end
def feed(pet : Animal, food : Food)
raise BadType.new should_be: Cat, actual: pet.class if food == "fish" && !pet.is_a?(Cat)
end
But, Class is abstract so cannot be used here as a field type.
So, how to solve this in my case? I hadn't found any derived class of Class, so does it mean one can never store a Class object as a field? But here my problem is a meaningful usage for this (any type check depends on input may require this BadType).
I'm not sure whether I missed something, so I came here first.

Class can't (yet) be used as a ivar type. Maybe it never will, I don't know.
But you can actually use generics for concrete data types, inferred from the arguments to the constructor:
# possible workaround
class Foo(T, U)
def initialize(#bar : T, #baz : U)
end
end
Foo.new String, Int32
I don't know your exact use case, but chances are you don't really need these values as classes. You probably can't do much with it anyway and drawing from your example I guess it's mostly for showing debugging information.
So it is very likely that just storing the names of the classes (as strings) would be a better solution for this problem.
# better solution
class Foo
#bar : String
#baz : String
def initialize(bar : Class, baz : Class)
#bar = bar.name
#baz = baz.name
end
end
Foo.new String, Int3
The generic arguments mean a new concrete type is created for every combination of classes used with Foo. That can have an impact on compiler performance.
I would most definitely use strings for this. Even if you need the classes for some particularly processing later on, it's probably better to just map the strings to the constants using a macro-generated lookup table.

Try generics:
class BadType(ClassA, ClassB) < Exception
getter should_be : ClassA
getter actual : ClassB
def initialize(#should_be, #actual)
#message = "Bad type: should be #{#should_be}, actual is #{#actual}"
end
end
def feed(pet : Animal, food : Food)
raise BadType(Animal.class, Animal.class).new should_be: Cat, actual: pet.class if food == "fish" && !pet.is_a?(Cat)
end
class Animal
end
record Food, food : String do
def ==(other_food)
#food == other_food
end
end
class Cat < Animal
end
class Dog < Animal
end
feed pet: Dog.new, food: Food.new("fish")
Output:
Unhandled exception: Bad type: should be Cat, actual is Dog (BadType(Animal:Class, Animal:Class))
from /eval:11:3 in 'feed'
from /eval:29:1 in '__crystal_main'
from /usr/lib/crystal/crystal/main.cr:104:5 in 'main_user_code'
from /usr/lib/crystal/crystal/main.cr:93:7 in 'main'
from /usr/lib/crystal/crystal/main.cr:133:3 in 'main'
from __libc_start_main
from _start
from ???
Demo: https://carc.in/#/r/4pgs

Related

Can I use a dictionary to call methods from different classes that inheritate from the same class?

I have two classes that inherit from the same base class, and they have some common methods (in fact, properties). I will need to do this:
input: an int and an object from either class;
output: the result of one of the methods (determined by the int) of the corresponding class.
I think I can use a dictionary to do this, as the following code:
class ChangeInt(object):
def bar(self, i):
print(i)
class PlusOne(ChangeInt):
def bar(self, i):
print(i+1)
class PlusTwo(ChangeInt):
def bar(self, i):
print(i+2)
methods_dict = {0:ChangeInt.bar}
print(methods_dict[0](PlusOne(), 0))
print(methods_dict[0](PlusTwo(), 0))
I expect the output to be 1,2, but I actually get this:
0
None
0
None
I would like to know how these results are generated and what should I do to fix it up. Thanks in advance.
I totally mess up the format in the comment, so I'll paste it here.
thanks to Ryan Haining in Dynamic Method Call In Python 2.7 using strings of method names, I've found another way to do this:
class ChangeInt(object):
def bar(self, i):
print(i)
class PlusOne(ChangeInt):
def bar(self, i):
print(i+1)
class PlusTwo(ChangeInt):
def bar(self, i):
print(i+2)
methods_dict = {0:'bar'}
getattr(PlusOne(), methods_dict[0])(0)
getattr(PlusTwo(), methods_dict[0])(0)
This may not be the best way to do it, but it produces the expected result:
class ChangeInt(object):
def bar(self, i):
if not ('ChangeInt' in str(self.__class__)):
self.bar(i)
else:
print(i)
class PlusOne(ChangeInt):
def bar(self, i):
print(i+1)
class PlusTwo(ChangeInt):
def bar(self, i):
print(i+2)
methods_dict = {0:ChangeInt.bar}
methods_dict[0](ChangeInt(), 0)
methods_dict[0](PlusOne(), 0)
methods_dict[0](PlusTwo(), 0)
and prints:
0
1
2
The bar() function in the base class calls the method associated with given self instance or the base class implementation if it's an instance of base class itself (just print(i)). This is important, without it the code will be calling self.bar(i) infinitely if you invoke it on the base class (i.e. until it reaches max allowable recursion call number).
The check if not ('ChangeInt' in str(self.__class__)): is necessary since issubclass will return True for the parent class too,
issubclass(class, classinfo)
Return true if class is a subclass
(direct, indirect or virtual) of classinfo. A class is considered a
subclass of itself. classinfo may be a tuple of class objects, in
which case every entry in classinfo will be checked. In any other
case, a TypeError exception is raised.
And the point is to distinguish between the base/parent class and any subclasses.
Finally, since your function calls don't return anything explicitly, they actually return None. That None is what you are printing when enclosing the calls in an additional print,
print(methods_dict[0](PlusOne(), 0))
I removed the extra print so you only print the (assuming) intended content.

Can I name a type in Crystal for convenience?

In my new crystal project, I have a class which is storing its data in a couple of different ways that are useful to me later, both as hashes.
getter isometry_cardinality : Hash(IsometryKind, Int8)
getter axis_cardinality : Hash(Directions::Orientation, Array(IsometryKind))
I'd like to overload my methods now based on which hash its using:
private def has_min_cardinality?(parent_cardinality : Hash(IsometryKind, Int8))
...
end
private def has_min_cardinality?(parent_cardinality : Hash(Directions::Orientation, Array(IsometryKind))
...
end
as you can see, that declaration is getting pretty long. Is there some convenient way to shorten it? For example, can I use the getter as an alias for its type?
private def has_min_cardinality?(parent_cardinality : isometry_cardinality)
...
end
private def has_min_cardinality?(parent_cardinality : axis_cardinality)
...
end
The answer is 'no' to that specific example, so my question is: am I missing the right way to do this?
Yes, there is a better way: alias to the rescue!
You can alias complex types like in this example and use the alias, the compiler just replaces it outright so there's no performance penalty.
alias IsometryCardinality = Hash(IsometryKind, Int8)
alias AxisCardinality = Hash(Directions::Orientation, Array(IsometryKind))
getter isometry_cardinality : IsometryCardinality
getter axis_cardinality : AxisCardinality
...
private def has_min_cardinality?(parent_cardinality : IsometryCardinality)
...
end
private def has_min_cardinality?(parent_cardinality : AxisCardinality)
...
end
Here's a demo: https://play.crystal-lang.org/#/r/4hoh

Covariance and Scala Collections

I'm trying to get my head around the covariance of Scala's collections. I have the following:
abstract class MediaFormat{
def name:String
def status:String
}
case class H264_high(status:String="on") extends MediaFormat {
def name = "h264_high"
}
case class H264_med(status:String="on") extends MediaFormat {
def name = "h264_med"
}
case class H264_low(status:String="on") extends MediaFormat {
def name = "h264_low"
}
case class H264_syndication(status:String="off") extends MediaFormat {
def name = "h264_syndication"
}
What I wanted to do was have a set of all of these formats because I need a collection where each format only occurs once, so I tried:
object MediaFormat {
val allFormats:Set[MediaFormat] = Set(H264_high,H264_low)
}
This gave me a compile time exception because, as I now understand, Set is invariant.
So I think, well I guess I'll just have to use a List and manage the repeated values myself
but then I try this:
object MediaFormat {
val allFormats:List[MediaFormat] = List(H264_high,H264_low)
}
because as I understand it, List is covariant, but that still doesn't compile.
Can someone help me understand what I should do to get a collection of my formats?
It doesn't compile because you are referencing the companion object (module), not the case classes! The compile error (which you should have posted) is nothing to do with variance. It will work, with Set if you do this:
val allFormats: Set[MediaFormat] = Set(H264_high(), H264_low())
^^ ^^
Or alternatively;
val allFormats = Set[MediaFormat](H264_high(), H264_low())
However, it makes no sense for these to be case classes given your description of the problem; I would just make them modules, i.e.
case object H264_syndication extends MediaFormat {
def status = "off"
def name = "h264_syndication"
}
Then your original code will work just fine. Or I would make them vals as follows:
case class MediaFormat(status: String, name: String)
val H264_syndication = MediaFormat(status ="off", name = "h264_syndication")
I think this would be my preference; I rarely use abstract classes any more to be honest (normally, I am dishonest).
Explanation: Covariance means the following:
G[S] <: G[T] iff S <: T
The fact that Set is invariant, means that a Set[S] is not a subtype of Set[T] (for S <: T), but it does not mean that such a Set[T] may not contain elements of type S.

Why aren't type parameters allowed in Scala auxiliary constructors?

Say I'm defining a simple 2D point class in Scala, and I want to be able to construct it with various types:
class Point(x:Float, y:Float) {
this(x:Double, y:Double) = this(x.toFloat, y.toFloat)
this(x:Int, y:Int) = this(x.toFloat, y.toFloat)
// etc...
}
I want to boil this down using a template, such as:
class Point(x:Float, y:Float) {
this[T](x:T, y:T) = this(x.toFloat, y.toFloat)
}
I know this won't work anyway, since T could be a type for which toFloat isn't defined, but the compiler error I get is:
no type parameters allowed here
Is this just unsupported in Scala? If so, why, and is there any simple way to get around this?
Scala's class constructors (unlike Java's) can't take type parameters, only the class itself can. As to why Scala made this design choice, I assume the main reason is simplicity.
If you want a secondary "builder" method that is generic, the natural thing to do is define it on the companion object. For example,
object Point {
def build[T : Numeric](x: T, y: T) = {
val n = implicitly[Numeric[T]]
new Point(n.toFloat(x), n.toFloat(y))
}
}
class Point(val x:Float, val y:Float)
val p = Point.build(1, 2) // Companion object's builder
p.x + p.y
Here I've used the Numeric typeclass to get a generic toFloat method.
I played with this for awhile, getting as "close" as...
class Point(x:Float, y:Float) {
def this[T <: Any { def toFloat: Float }](x:T, y:T) = this(x.toFloat, y.toFloat)
}
...which results in "error: no type parameters allowed here" (just as per the post) and then I realized...
If the initializer could take type parameters it would be ambiguous with the class parameters, if any. Not that this couldn't be worked about in the language specification... but it is a more complex case at the very least. There might also be Java interoperability issues.
Imagine:
class Foo[T](x: T) {
def this[X](z: X) = ...
}
new Foo[Int](42) // T is Int? X is ...? Or ...?
Personally I wish Scala followed an Eiffel-like pattern (only named constructors or "factory methods"), but alas, that would not be Scala.
Happy coding.

Code Design / Testability How To?

My team is designing a library that is wrapping calls to Active Directory to search and return a list of people.
We have a person class that wraps up the information for a person found. We then use the List to wrap them up. When we call the search it uses the internal System.Directory library and returns a SearchResultCollection object. We then iterate through it to build up the list<> and return that.
We have designed the person class to only have read only (get) properties since we don't want the callee to change the person info. We pass in the SearchResult object from the System.Directory library on the constructor of the person.
My issue is we can't test this easily.
My thoughts so far have been:
Pass variables into the person constructor for each property needing to be set.
Unfortunately, this will make for a very long constructor parameter list.... Smells bad to me.
Allow the person class to have setters on the properties.
Again, smells bad to me since we can't control the callee from using this.
Refactor:
I have looked at the extract to interface and adapt parameter techniques. It seems the adapt parameter has the most promise? Adapt parameter seems nice because it does help break the dependency I have on the Directory Library's SearchResult object. So if in the future I wanted to do some other kind of search we are in good shape. At least I think we are?
Sub class the person object and create a test Person with setters....
Seems like it would work but not sure if it's the right way to go?
Mock it
Haven't done any mocking yet so again not sure on this one.
EDIT: If mocking is best idea please let me know... However, I would be interested to know how this would be done without mocking also (or perhaps it really isn't do able without mocking)....
I would appreciate guidance on this one.
Here's a snippet of the code:
public class PeopleSearcher
{
.... declarations left out....
public List<Person> FindPerson(string FirstName, string LastName, string Login)
{
...filter setup left out for brevity....
_peopleFound = _directoryToSearch.FindAll();
//Convert to list of persons....
int cnt = 0;
_listOfPeople = new List<Person>();
while (cnt < _peopleFound.Count)
{
Person p = new Person(_peopleFound[0]);
_listOfPeople.Add(p);
cnt++;
}
return _listOfPeople;
}
}
public class Person
{
private string sn;
....further declarations left out for brevity....
public Person(SearchResult PersonFound)
{
sn = PersonFound.Properties["sn"].Count == 0 ? string.Empty : PersonFound.Properties["sn"][0].ToString();
givenName = PersonFound.Properties["givenName"].Count == 0 ? string.Empty : PersonFound.Properties["givenName"][0].ToString();
sAMAccountName = PersonFound.Properties["sAMAccountName"].Count == 0 ? string.Empty : PersonFound.Properties["sAMAccountName"][0].ToString();
adsPath = PersonFound.Path == null ? string.Empty : PersonFound.Path;
}
public string LastName
{
get
{
return sn;
}
}
.... more getters...
}
}
"Mocking" is a word that is usually used for all kinds of test doubles. And most times people or not "mocking", they're faking or stubbing. Anyway, your 4th option (subclass and add setters) sounds to me like the easiest way to go given your codebase assuming you want Person objects to pass toother methods. Because I don't think you're talking about testing that the person object gets the properties set correct by the constructor, right?
Mock it. This is the sort of situation that mocking was invented for. I've only done mocking in Ruby, so I'm not sure of the state of the art for .net, but it should work well.
When mocking it you might realize some areas that should be refactored. This is also a good plan.
In your mock (by framework or otherwise), you're still going to end up having to create Person objects with values, which leads you right back to your original problem.
Fortunately, there are two excellent solutions:
1) Go ahead and add setters to the Person class, but make them protected. This means your mock and test code would have to be in the same package, but would block other users from mutating your Persons. (and we don't want mutants running around - there's been enough of that in the movies lately).
2) Use a Builder class (as Joshua Bloch describes in Effective Java). You'd create a public static PersonBuilder class inside Person, which would export a build method and chainable parameter specifiers (like setters, but not separately callable):
public class Person ....
public static class PersonBuilder {
public PersonBuilder (String firstName, String lastName) {...} // my sample has two required values
public Person build() { ... }
public PersonBuilder ssn (String value) { ... }
public PersonBuilder adsPath (String value) { ... }
...
}
...
}
The chainable value specifiers look like this:
public PersonBuilder ssn (String value) {
this.sn = value;
return this;
}
Then a call to create a Person looks like this:
Person thisPerson = new Person.PersonBuilder ("John", "Smith").ssn("123-45-6789").adsPath("whatever");
This method completely hides the methods which can set the values (indeed, you have no "setters"), but keeps you from having to deal with long constructor argument lists (which makes it easier to deal with optional values).
Incidentally, you also probably want to make Person's constructor private.