I am trying to define a pointcut which will capture all the constructor calls, regardless of the modifier, return type, or class. I have used the following code
after():execution(* * * .new(..))
I am having an error :
Syntax error on token "*", "(" expected.
Can anybody suggest what may be the right approach?
Just remove the middle star "*". It does not make sense to specify a return type for a constructor call because it is clear that the constructor will always return an instance of the class it is defined for.
after() : execution(* *.new(..))
BTW, you should also remove the whitespace before ".new".
Related
I fail to understand, why the following compiles:
directory.listFiles { it -> it.name.startsWith("abc") }
but this doesn't:
directory.listFiles { it.name.startsWith("abc") }
Am I correctly assuming that in the first case, the type of it is inferred via the name property? Why is this not happening in the second case?
It is because there are two possible FunctionalInterfaces that can be used with File.listFiles:
listFiles(FileFilter) - this interface is accept(File pathname)
listFiles(FilenameFilter) - this interface is accept(File dir, String name)
The compiler cannot work out which you want to use. So how is this better in the case you write it ->?
Well, the compiler inspects the call arguments of the two interface methods and can now see you expect one argument "SOMETHING ->," so the only matching call is the FileFilter variation.
How might you use the FilenameFilter? you'd use this syntax:
directory.listFiles { dir, name -> name.startsWith("abc") }
The magic here is not it - that's a coincidence, but that you declared just one parameter.
I have this action which overrides an action in another action class:
method taskwiki-prefix($/ is copy) {
my $prefix = $/.Str;
$prefix ~~ s:g!'|'!!;
make $prefix;
}
The substitution throws this error:
P6opaque: no such attribute '$!made' on type Match in a List when trying to bind a value
If I comment out the substitution, the error goes away. dd $prefix shows:
Str $prefix = " Tasks ||"
So it's just a plain string.
If I remove the :g adverb, no more error, but doing that makes the made value Nil and nothing shows up in the output for $<taskwiki-prefix>.made.
Looks to me like there is some bad interaction going on with the matches in the substitution and the action, if I were to guess.
Any fix?
This is another case of your previous question, Raku grammar action throwing "Cannot bind attributes in a Nil type object. Did you forget a '.new'?" error when using "make". As there, the make function wants to update the $/ currently in scope.
Substitutions update $/, and:
In the case of the :g adverb, a List ends up in $/, and make gets confused. I've proposed an improved error.
In the case of no :g, there is a Match in $/ and it is attached to that - however, it's no longer the Match object that was passed into the method
I recommend to:
Always have the signature of your action methods be ($/), so there's no confusion about the target of make.
When possible, avoid reparsing (which was the achieved solution mentioned in your own answer).
If you can't avoid doing other matches or substitutions in your action method, put them in a sub or private method instead and then call it.
Problem was solved by changing the the grammar to give me a cleaner output so I did not have to manipulate the $/ variable.
Sorry for the terrible title, but I can't seem to find an allowable way to ask this question, because I don't know how to refer to the code constructs I am looking at.
Looking at this file: https://github.com/Hexworks/caves-of-zircon-tutorial/blob/master/src/main/kotlin/org/hexworks/cavesofzircon/systems/InputReceiver.kt
I don't understand what is going on here:
override fun update(entity: GameEntity<out EntityType>, context: GameContext): Boolean {
val (_, _, uiEvent, player) = context
I can understand some things.
We are overriding the update function, which is defined in the Behavior class, which is a superclass of this class.
The update function accepts two parameters. A GameEntity named entity, and a GameContext called context.
The function returns a Boolean result.
However, I do not understand the next line at all. Just open and close parentheses, two underscores as the first two parameters, and then an assignment to the context argument. What is it we are assigning the value of context to?
Based on IDE behavior, apparently the open-close parentheses are related to the constructor for GameContext. But I would not know that otherwise. I also don't understand what the meaning is of the underscores in the argument list.
And finally, I have read about the declaration-site variance keyword "out", but I don't really understand what it means here. We have GameEntity<out EntityType>. So as I understand it, that means this method produces EntityType, but does not consume it. How is that demonstrated in this code?
val (_, _, uiEvent, player) = context
You are extracting the 3rd and 4th value from the context and ignoring the first two.
Compare https://kotlinlang.org/docs/reference/multi-declarations.html .
About out: i don't see it being used in the code snippet you're showing. You might want to show the full method.
Also, maybe it is there only for the purpose of overriding the method, to match the signature of the function.
To cover the little bit that Incubbus's otherwise-great answer missed:
In the declaration
override fun update(entity: GameEntity<out EntityType>, // …
the out means that you could call the function and pass a GameEntity<SubclassOfEntityType> (or even a SubclassOfGameEntity<SubclassOfEntityType>).
With no out, you'd have to pass a GameEntity<EntityType> (or a SubclassOfGameEntity<EntityType>).
I guess that's inherited from the superclass method that you're overriding. After all, if the superclass method could be called with a GameEntity<SubclassOfEntityType>, then your override will need to handle that too. (The Liskov substitution principle in action!)
I'm taking my first steps with kotlin.
I am migrating some my existing java code to kotlin.
I have the folllowing line:
storyDate.ifPresent(article::setPublishDate);
Where storyDate is an Optional and article has a method setPublishDate(Date) method.
How would I migrate this line to kotlin?
The auto migrator at https://try.kotlinlang.org is
storyDate.ifPresent(Consumer<Date>({ article.setPublishDate() }))
But this line doesn't compile with the kotlin compiler.
I strongly prefer using extension functions and extension fields, so I've written smth like
val <T> Optional<T>.value: T?
get() = orElse(null)
And then you can use it anywhere (after import) like
myOptional.value?.let {
// handle here
}
It’s rather uncommon to use Optional in Kotlin. If you can make storyDate work as an ordinary unwrapped type, such constructs can often be expressed with a simple let call:
storyDate?.let {
article.setPublishDate(it)
//probably property access works as well:
article.publishDate = it
}
How it works: The safe call ?. will invoke let only if storyDate is not null, otherwise the whole expression evaluates to, again, null. When the variable is not null, let is called with a simple lambda where storyDate is accessible by it (or you can rename it to whatever you like).
Side note:
If storyDate really must be Optional, you can still use the depicted construct by unwrapping it like this:
storyDate.orElse(null)?.let {}
storyDate.ifPresent { Article.setPublishDate(it) }
or
storyDate.ifPresent(Article::setPublishDate)
will work.
In the first example, it denotes the value in the optional instance, which is the Date in the optional storyDate.
I assumed that Article is a class, which has the setPublishDate(Date) static method, because class names are always capitalized.
But if article is an instance, not a class, and it has non-static method, then the following will work.
// article = Article(/* some Article-typed object */)
storyDate.ifPresent { article.setPublishDate(it) }
it has the same meaning as the above one, i.e., the actual Date value in Optional.
I am currently writing a wrapper for a native C++ class in CLI/C++. I am on a little GamePacket class at the moment. Consider the following class:
public ref class GamePacket
{
public:
GamePacket();
~GamePacket();
generic<typename T>
where T : System::ValueType
void Write(T value)
{
this->bw->Write(value);
}
};
I want that I'm able to call the function as following in C#, using my Wrapper:
Packet.Write<Int32>(1234);
Packet.Write<byte>(1);
However, I can't compile my wrapper. Error:
Error 1 error C2664: 'void System::IO::BinaryWriter::Write(System::String ^)' : cannot convert argument 1 from 'T' to 'bool'
I don't understand this error, where does the System::String^ comes from. I'm seeing a lot of overloads of the Write() method, does CLI/C++ not call the correct one, and if so, how can I make it call the correct one?
Reference MSDN: http://msdn.microsoft.com/en-us/library/system.io.binarywriter.write(v=vs.110).aspx
Templates and generics don't work the same.
With templates, the code gets recompiled for each set of parameters, and the results can be pretty different (different local variable types, different function overloads selected). Specialization makes this really powerful.
With generics, the code only gets compiled once, and the overload resolution is done without actually knowing the final parameters. So when you call Write(value), the only things the compiler knows is that
value can be converted to Object^, because everything can
value derives from ValueType, because your constraint tells it
Unfortunately, using just that information, the compiler can't find an overload of Write that can be used.
It seems like you expected it to use Write(bool) when T is bool, Write(int) when T is int, and so on. Templates would work like that. Generics don't.
Your options are:
a dozen different copies of your method, each of which has a fixed argument type that can be used to select the right overload of BinaryWrite::Write
find the overload yourself using reflection, make a delegate matching the right overload, and call it
use expression trees or the dynamic language runtime to find and make a delegate matching the right overload, and then you call it