I know it's not 'possible' to mock free functions yet, so I wondered if I could create macro that does this for me. Ideally I could just copy what's inside the MOCK_METHOD and paste it in MOCK_FREE kind of macro.
#define MOCK_FREE_VOID(ret, name, args, ...) ret name args { Mockups::GetInstance()->name (__VA_ARGS__); }
#define MOCK_FREE_NON_VOID(ret, name, args, ...) ret name args { return Mockups::GetInstance()->name (__VA_ARGS__); }
class Mockusp {
public:
MOCK_METHOD(void, fun_foo, (foo_t foo, bar_t bar))
MOCK_METHOD(bar_t, fun_bar, (foo_t foo, bar_t bar))
...
}
// This works
MOCK_FREE_VOID(void, fun_foo, (foo_t foo, bar_t bar), foo, bar)
MOCK_FREE_NON_VOID(bar_t, fun_bar, (foo_t foo, bar_t bar), foo, bar)
// I'd like to have
MOCK_FREE_VOID(void, fun_foo, (foo_t foo, bar_t bar))
MOCK_FREE_NON_VOID(bar_t, fun_bar, (foo_t foo, bar_t bar))
Which creates me free functions and passes their parameters to the mock:
void fun_foo (foo_t foo, bar_t bar) { Mockups::GetInstance()->fun_foo (foo, bar); }
bar_t fun_bar (foo_t foo, bar_t bar) { return Mockups::GetInstance()->fun_bar (foo, bar); }
At the moment, my macro requires one to append parameter names to the end, can I get rid of them?
Related
I really like how with behaves. Is it possible to extend with so it works with multiple params.
I want to use with like this.
with(foo, bar){
fooFunction()
barFunction()
}
First, I strongly against it.
One can come close to what you want:
data class A(val a: Int)
data class B(val b: Int)
fun<S, T> withPair(a: S, b: T, f: S.() -> T.() -> Unit) {
val g = a.f()
b.g()
}
fun main() {
withPair(A(1), B(2)) {{
print(a)
print(b)
}}
}
So you can have a block function which return a block function. You need nested lambdas though.
I don't think it's possible to write a function which behaves like this, but with the standard with you can write
with(foo) {
with(bar) {
fooFunction()
barFunction()
}
}
(note that if a method is available on both foo and bar, this way the bar method will be called).
Another possibility is to use a Pair, something like:
with( Pair("abc" , listOf(1,2,3)) ) {
println(first.plus("d"))
println(second.reversed())
}
Prints:
abcd
[3, 2, 1]
It's impossible to do this with the standard with function because it cannot have two receiver types of the lambda (accessed by this).
with(foo, bar){
fooFunction() //`this` would have to mean `foo`
barFunction() //`this` would have to mean `bar`
}
Nesting two withs is nasty. It can cause all sort of issues, with this ambiguity...
That said, you can create your own with function that will work similarly to the standard one, but will not use passed extension fun (so no receiver type "hidden" behind this), but a regular lambda with two arguments:
inline fun <T1, T2, R> with(t1: T1, t2: T2, block: (T1, T2) -> R): R {
return block.invoke(t1, t2)
}
//then:
with(foo, bar) { f, b ->
f.fooFunction()
b.barFunction()
}
I often want to test that I've defined a method in a particular class. This has caught many problems where I've renamed a method or otherwise rearranged things in the architecture.
I know I can use .^lookup but that still feels weird to me like I'm eventually going to run into a case where it returns things in a different order than I expect (ignore signatures for now). This is what I came up with:
use Test;
class Foo is Str {}
class Bar is Str { method Str { 'Hello' } }
can-ok Str, 'Str';
can-ok Foo, 'Str';
can-ok Bar, 'Str';
is Foo.^lookup( 'Str' ).package.^name, 'Foo', 'Foo defines Str';
is Bar.^lookup( 'Str' ).package.^name, 'Bar', 'Bar defines Str';
done-testing;
It does what I want in this simple case and I haven't made it fail so far:
ok 1 - The type 'Str' can do the method 'Str'
ok 2 - The type 'Foo' can do the method 'Str'
ok 3 - The type 'Bar' can do the method 'Str'
not ok 4 -
ok 5 -
1..5
# Failed test at /Users/brian/Desktop/hello.p6 line 12
# expected: 'Foo'
# got: 'Mu'
# Looks like you failed 1 test of 5
You should not be comparing types by name.
my \Foo = anon class Foo {}
my \Bar = anon class Foo {}
say Foo.^name eq Bar.^name; # True
say Foo eqv Bar; # False
In fact is checks for object identity if you give it a type object as the second argument.
is Bar.^lookup( 'Str' ).package, Bar, 'Bar defines Str'
You could always add a subroutine to add clarity.
sub defines-method (
Mu:U $class,
Str:D $method,
Str:D $desc = "$class.^name() defines $method"
) {
is $class.^lookup( $method ).?package, $class, $desc
}
defines-method Foo, 'Str';
You could alias it to an operator
sub &infix:<defines-method> = &defines-method;
Bar defines-method 'Str';
(Note that I used .?package in case .^lookup doesn't return anything.)
.^lookup gives you the Method object that will be called; so I don't know why you are talking about it giving you them in a different order when there is only one value returned. If there are multi methods it returns the proto method (possibly implicitly created).
If you want the individual multi methods you would call .candidates on it.
(There is also .^find_method, and off the top of my head I don't remember the difference)
I believe you are thinking of .can which gives you the Method objects in the order they would be called if you used .*Str or .+Str, which is the same as the method resolution order. Which means it would only change if you change the inheritance tree.
> class Bar is Str { method Str { 'Hello' } }
> quietly .perl.say for Bar.+Str;
"Hello"
""
""
> .perl.say for Bar.new.+Str
"Hello"
""
"Bar<80122504>"
> quietly .(Bar).perl.say for Bar.can('Str')
"Hello"
""
""
> .(Bar.new).perl.say for Bar.can('Str')
"Hello"
""
"Bar<86744200>"
I am trying to rewrite from Objective-C to Swift, I cannot work out the syntax or understand the docs
Here is a simplified example in Objective-C I wrote:
[UIView animateWithDuration:10.0 animations:^{self.navigationController.toolbar.frame = CGRectMake(0,10,0,10);}];
How do I write this in Swift?
This is the template autocomplete gives:
UIView.animateWithDuration(duration: NSTimeInterval, animations: (() -> Void))
This is the swift closure format:
{(parameter:type, parameter: type, ...) -> returntype in
//do stuff
}
This is what you should do:
//The animation closure will take no parameters and return void (nothing).
UIView.animateWithDuration(duration: NSTimeInterval, animations: {() -> Void in
//Animate anything.
})
Here is the documentation for closures.
Since the expected argument types and return type to the animations argument are known the compiler can infer them without a problem. This should work (though I don't have the playground available right at the moment:
UIView.animateWithDuration(10.0, animations: {
self.navigationController.toolbar.frame = CGRect(x:0.0, y:10.0, width:10.0, height:0.0)
})
for more info about closures see the chapter in the swift docs
note about CGRect() - the developer docs show CGRect() being used in swift code. Perhaps it requires an import?
update for comments: you can also use a trailing closure like so:
UIView.animateWithDuration(10.0) {
self.navigationController.toolbar.frame = CGRect(x:0.0, y:10.0, width:10.0, height:0.0)
}
Following code can guide to write your own block.
class func testFunc(completion: ((list : NSArray!) -> Void)?) {
//--- block code.
if completion! != nil {
completion! (list: NSArray())
}
}
and you can call it like -
className.testFunc {
(list: NSArray!) -> Void in
}
You can basically write it in 3 identical ways:
write what to do right in the closure/code block:
UIView.animateWithDuration(10.0) {
self.navigationController.toolbar.frame = CGRect(x:0.0, y:10.0, width:10.0, height:0.0)
}
This is also known as trailing closure ( You can only do trailing closure if the closure parameter is the last parameter)
This doesn't mean the parameter 'animations' is no longer written. It is written but just as in the format of above.
Write exactly within the lines, most developers avoid such, because it's a little buggy to write with all the parenthesis and braces.
UIView.animateWithDuration(10.0, animations: {
self.navigationController.toolbar.frame = CGRect(x:0.0, y:10.0, width:10.0, height:0.0)
})
(Contrary to trailing closure you wrote name ie 'animations')
This is known as inline closure
Write in a more modular sense
UIView.animateWithDuration(duration: NSTimeInterval, animations: animatingFunc)
func animatingFunc() {
self.navigationController.toolbar.frame = CGRect(x:0.0, y:10.0, width:10.0, height:0.0)
}
Remember the type of the parameter 'animations' was () -> Void
Exactly as what we are doing, animatingFunc takes no parameters ie '()' and returns nothing ie 'void'
(In Swift, functions are types and can be passed in as parameters)
Some might say this is more readable some might say trailing closure is...
Side note1
You can also do nothing ( which really doesn't make sense but in many other handlers/animations/completion handlers you may not want to do anything)
UIView.animateWithDuration(duration: NSTimeInterval, animations: nil)
Side note2
Closures becomes more interesting when you have to capture a value. See this simple demonstration.
For more information about Swift closures see Apple's Documentation
How Do I Declare a Closure in Swift?
As a variable:
var closureName: (ParameterTypes) -> ReturnType
As an optional variable:
var closureName: ((ParameterTypes) -> ReturnType)?
As a type alias:
typealias ClosureType = (ParameterTypes) -> ReturnType
As a constant:
let closureName: ClosureType = { ... }
As a parameter to another function:
funcName(parameter: (ParameterTypes) -> ReturnType)
Note: if the passed-in closure is going to outlive the scope of the method, e.g. if you are saving it to a property, it needs to be annotated with #escaping.
As an argument to a function call:
funcName({ (ParameterTypes) -> ReturnType in statements })
As a function parameter:
array.sorted(by: { (item1: Int, item2: Int) -> Bool in return item1 < item2 })
As a function parameter with implied types:
array.sorted(by: { (item1, item2) -> Bool in return item1 < item2 })
As a function parameter with implied return type:
array.sorted(by: { (item1, item2) in return item1 < item2 })
As the last function parameter:
array.sorted { (item1, item2) in return item1 < item2 }
As the last parameter, using shorthand argument names:
array.sorted { return $0 < $1 }
As the last parameter, with an implied return value:
array.sorted { $0 < $1 }
As the last parameter, as a reference to an existing function:
array.sorted(by: <)
As a function parameter with explicit capture semantics:
array.sorted(by: { [unowned self] (item1: Int, item2: Int) -> Bool in return item1 < item2 })
As a function parameter with explicit capture semantics and inferred parameters / return type:
array.sorted(by: { [unowned self] in return $0 < $1 })
This site is not intended to be an exhaustive list of all possible uses of closures. ref: http://goshdarnclosuresyntax.com/
Is it possible to specify some optional parameter(s) to the 'at' closure on the page like this:
class ManagerDashboardClientsPage extends Page {
static at = { year, geo ->
if (year) {
GebUtil.selectedYear == year
}
title.endsWith('Dashboard: Clients')
}
}
so that I can write both
at ManagerDashboardClientsPage
and
at ManagerDashboardClientsPage(2013, 'North East')
Currently the first one breaks with
No signature of method: page.ManagerDashboardClientsPage$__clinit__closure1.doCall() is applicable for argument types: () values: []
Possible solutions: doCall(java.lang.Object, java.lang.Object), call(), call([Ljava.lang.Object;), call(java.lang.Object), call(java.lang.Object, java.lang.Object), equals(java.lang.Object)
groovy.lang.MissingMethodException: No signature of method: page.ManagerDashboardClientsPage$__clinit__closure1.doCall() is applicable for argument types: () values: []
Possible solutions: doCall(java.lang.Object, java.lang.Object), call(), call([Ljava.lang.Object;), call(java.lang.Object), call(java.lang.Object, java.lang.Object), equals(java.lang.Object)
at geb.Page.verifyThisPageAtOnly(Page.groovy:165)
at geb.Page.verifyAt(Page.groovy:133)
at geb.Browser.doAt(Browser.groovy:358)
at geb.Browser.at(Browser.groovy:289)
at geb.spock.GebSpec.methodMissing(GebSpec.groovy:51)
at spec.ManagerDashboardClientsSpec.login as CEO(ManagerDashboardClientsSpec.groovy:16)
In Groovy you can set default values for optional closure parameters, like so:
static at = { year=null, geo=null ->
...
}
I think that'll clear ya up. :)
update
Ok, I know you don't need it anymore, but I made this for my own use when I was learning Groovy, and I thought someone might find it helpful:
{ -> ... } a closure with exactly zero parameters. Groovy will blow up if you call it with params.
{ ... } a closure with one optional parameter, named "it"
{ foo -> ... } a closure with one parameter named "foo" (foo can be any type)
{ foo, bar, baz -> ... } a closure with 3 parameters named "foo", "bar" and "baz"
{ String foo -> ... } You can specify the type of the parameters if you like
My question:
Why is callNextMethod() not passing arguments as expected to the next method?
Situation:
Say I have two hierarchical classes foo and bar (bar is subclass of foo) for which I have a method foobar that can dispatch for both classes (i.e., has methods for both classes).
Furthermore, the method for the (sub)class bar calls the method for foo after some calculations with callNextMethod().
Both methods have the same additional argument (with default) that should be passed to the method for foo, where only it is relevant.
setClass("foo", representation(x = "numeric"))
setClass("bar", contains = "foo")
setGeneric("foobar", function(object, ...) standardGeneric("foobar"))
setMethod("foobar", "foo", function(object, another.argument = FALSE, ...) {
print(paste("in foo-method:", another.argument))
if (another.argument) object#x^3
else object#x^2
})
setMethod("foobar", "bar", function(object, another.argument = FALSE, ...) {
print(paste("in bar-method:", another.argument))
object#x <- sqrt(object#x)
callNextMethod()
})
Problem description:
The arguments are not passed as expected, but the default values are taken from the method definition. Specifically, in the first method the argument is as specified in the call (TRUE), however, it changes to FALSE in the next method.
o1 <- new("bar", x = 4)
foobar(o1, another.argument = TRUE)
gives
[1] "in bar-method: TRUE"
[1] "in foo-method: FALSE"
[1] 4
I want the another.argument to be passed to the next method so that it is TRUE in the call to the foo method, too.
From ?callNextMethod I get that it should work as expected (i.e., the named argument is passed as it is in the call):
For a formal argument, say x, that appears in the original call, there
is a corresponding argument in the next method call equivalent to x =
x. In effect, this means that the next method sees the same actual
arguments, but arguments are evaluated only once.
My second question: How can I pass another.argument to the next method. (I would really like to keep default arguments in both methods)
I think this has to do with the way a method with a signature different from the generic is defined (within a function .local)
> selectMethod(foobar, "bar")
Method Definition:
function (object, ...)
{
.local <- function (object, another.argument = FALSE, ...)
{
print(paste("in bar-method:", another.argument))
object#x <- sqrt(object#x)
callNextMethod()
}
.local(object, ...)
}
Signatures:
object
target "bar"
defined "bar"
The work-around is to either define the generic and methods to have the same signature
setGeneric("foobar",
function(object, another.argument=FALSE, ...) standardGeneric("foobar"),
signature="object")
or pass the arguments explicitly to callNextMethod
setMethod("foobar", "bar", function(object, another.argument = FALSE, ...) {
print(paste("in bar-method:", another.argument))
object#x <- sqrt(object#x)
callNextMethod(object, another.argument, ...)
})