I would like to create a macro that takes a string as a parameter and evaluates that to an object. Something like:
#macro( valueTest $objRef)
#define( $obj )#evaluate("$${objRef}")#end
$obj.foo ## This would have to be translated to $obj.getFoo()
#end
Unfortunately the $obj variable does not point to object reference that could be used to call methods. $obj is a String and $obj.foo does not try to execute getFoo.
Somewhy I have a feeling that this is the nature of evaluate and it is not possible to do what I want to.
the reason why I want to do smth like this is because we have quite few macros that take both command bind path and command itself as a parameter and I am hoping the latter could be derived from first.
Unfortunately, Velocity does not have a mechanism to define functions which return object references. Macros are really intended to be a shortcut to display text.
In cases like this, the way to proceed is generally to create a "tool" in Java and put an instance in the context. A tool is just an ordinary class with a method that returns what you are looking for
e.g.
create an object with an "eval" method, then put it in the context as "referenceEvaluator".
#set($obj = $referenceEvaluator.eval($objRef))
You might find that your code is clearer if you avoid the double evaluation and just insert an object into the context named $obj that does what you want. (better performance, too).
Related
If I pass an Object into the model and test it with the "?is_string" built-in, it will falsely return a true value.
Is it possible (without checking the class name) to have a proper type checks on Objects?
FreeMarker: 2.3.28
Code to reproduce:
public class Test {}
// In Test Controller
ModelAndView mv = new ModelAndView("test");
mv.addObject("test", new Test());
// In test.ftl
<#if test?is_string>
${test} - is a string!
</#if>
// Result
Test#455b31c - is a string
The problem is that that approach isn't really supported by FreeMarker. The Java objects are mapped to some template language values via Configuration.objectWrapper, and the template only sees the result of that mapping. Furthermore the template language has a different type system than Java, a simplistic one, without classes. (It was a design goal back then that the data-model is just some simple tree, and the templates will work no mater what objects are behind, as far as it still gives the same tree.) ?is_... doesn't check the Java type, but the type according the template language. As with the usual ObjectWrapper-s a "generic" object (means, nothing recognized like List, Map, Date, etc.) can be used as a strings whose value is whatever toString() returns, it's a string as far as the template language is concerned. It's kind of duck typed...
A workaround I can think of is that first check the value with ?is_hash, as that will catch the said generic objects (as they support ., they are hashes as well, not just strings). Or instead just check the property you expect to be present in a Test. Then on the "else" branch you can continue with ?is_string.
I have a constructor built function(Bond.Valuation). The result of which is a superclass of other classes, BondAnalytics. Now, from what I have read, I need to create methods on the class BondAnalytics. Reading Chambers book I have done the following:
When I type Bond.Valuation it says its a standard generic. So, show will work on it?
method.skeleton("show", c("BondAnalytics")).
So, I think this uses the generic function "show" on any object of BondAnalytics.
The command to method.skeleton produces:
setMethod("show",
signature(object = "BondAnalytics"),
function (object)
{
cat("Bond Valuation\n")
cat(BondID:);print(object#ID)
}
)
So, I think that show is a generic function that is now associated with this method and signature is class BondAnalytics, so this method will match itself to anything the matches class BondAnalytics.
So basically, I just have to define what I want to show from Bond.Valuation. What if I wanted a combination of text and a plot? Is that one method of methods in methods
That is correct. The method "show" you just declared will be associated with the BondAnalytics class. In this method you can do anything you want to. If you want to you can display summary statistics or plot some information about the object or do both.
This is from the manual for "show":
Display the object, by printing, plotting or whatever suits its
class. This function exists to be specialized by methods. The
default method calls ‘showDefault’.
It basically says you can do whatever you want to.
Can anyone tell me what is the main advantage of using tuple? In what scenarios do I need to use these?
I assume that you're talking about the Tuple<> type and not anonymous tuple classes.
Like an anonymous type, Tuple<> allows you to avoid declaring a new class just to group a few objects. Unlike anonymous types, tuple types have known names and thus can be used as method return and parameter values, etc.
Personally, I try to avoid heavy use of Tuple<> because it can make for difficult to understand code, expecially when used with primitive types (e. g. if you see a Tuple it's not obvious what each field represents).
One place I have found tuples to be very useful is as dictionary keys. Because Tuples implement Equals() and GetHashCode() (not ==, though!), they are perfect for things like private dictionaries that cache information based on a compound key.
It's used mostly to avoid declaring a class / struct with a few properties only for the sake of passing a group of objects around, where only one object can be passed.
Lets say I have a list of urls to go through and if i get an error (4xx or 5xx) I want to build a list and then either later display it to the user or just look at it in my debugger.
I'd catch the web exception and have a Tuple<string, int> (url, http error code) instead of creating a struct for one or two functions to use. Heck it might even be a foreach loop with a breakpoint on if the list has more then 0 items. Thats when it is useful.
I would like to store MetaObjects in a list like this:
myList = QList<QMetaObject>();
myList->append(MyClass::staticMetaObject);
myList->append(MyOtherClass::staticMetaObject);
I want to keep track of these object through out the application but I don't wish to allocate them just yet. By adding some information in my classes I will be able to use the MetaObject function "classInfo(int).value()". I use this when I store them in a QListWidget. When a row in the QListWidget is pressed I would like to be able to create an object of that specific kind that is stored in the list.
(Also have to add that all the classes dervies from the same baseclass)
This sample code describes a bit of what I want to do, except in his example, you add the classes as you go along.
http://lists.qt.nokia.com/pipermail/qt-interest/2012-January/037204.html
I read through the manual and when I try things like:
MyBaseClass *test = qobject_cast<MyBaseClass*>myList->at(i).newInstance();
The project compiles but when I try to print the "test" object its null. What am I doing wrong? And is this the best way of doing this?
Was also looking at MetaType, but where would i be able to store, for example a string for the menus if I'm not allowed to create the object? Would this be a nicer solution if I have a static function that returns a string?
Edit:
I now changed so the constructors are Q_INVOKABLE which solved the problem where "test == null".
But what are the downside of this solution? Should I just use a object factory (the old fashion way with a switch case)?
Is there any way to 'dynamically'/reflectively/etc create a new instance of a class with arguments in Scala?
For example, something like:
class C(x: String)
manifest[C].erasure.newInstance("string")
But that compiles. (This is also, rest assured, being used in a context that makes much more sense than this simplified example!)
erasure is of type java.lang.Class, so you can use constructors (anyway you don't need manifest in this simple case - you can just use classOf[C]). Instead of calling newinstance directly, you can at first find correspondent constructor with getConstructor method (with correspondent argument types), and then just call newInstance on it:
classOf[C].getConstructor(classOf[String]).newInstance("string")