Break out of an anonymous function in kotlin - loops

Created a test case to try and represent what I'm trying to do. I can't figure out how to "stop" continuing to do work inside of an anonymous function. In the example below I would like to break out of the "apple" section if the answer is correct. The code below doesn't compile because it says return#apple instead of return#banana which is the only valid option but I wrote it below to try and explain what I'm trying to achieve and better understand how to go about doing something like this.
class FunctionBreakingTest {
#Test fun stopInMiddleOfLambda() {
var answer = "wrong"
doStuff apple# {
doStuff banana# {
answer = "correct"
if (answer == "correct") {
return#apple
}
answer = "wrong"
}
answer = "wrong"
}
assertEquals("correct", answer)
}
private fun doStuff(foo: () -> Unit) = foo.invoke()
}

You need to make doStuff an inline function: non-local return is only supported for lambdas that are inlined.
private inline fun doStuff(foo: () -> Unit) = foo.invoke()
Then your test case passes.

Not only is return#apple illegal, just plain return is also illegal (because the non-local return requires inlining - See the answer by #hotkey, make doStuff inline and then it works)...
(Note that such non-local returns are supported only for lambda expressions passed to inline functions.)
This section of the Kotlin Documentation covers Returns at labels. Note: using anonymous functions instead of lambdas would allow you to eliminate the labels if you wanted (but, you only get local returns, and you would need to modify your code slightly).
#Test fun stopInMiddleOfLambda() {
var answer = "wrong"
doStuff(fun() {
doStuff(fun() {
answer = "correct"
if (answer == "correct") {
return
}
answer = "wrong"
})
if(answer != "wrong") {
return
}
answer = "wrong"
})
assertEquals("correct", answer)
}
...

Related

How to get the class of a VALUE in Ruby C API

I created some classes with Ruby's C API. I want to create a function whose behavior will change depending on the class of the Ruby object.
I tried to use is_a? from Ruby, however, I don't think it's the good way to do this. I checked "Creating Extension Libraries for Ruby" without success. The only direct way to check classes is with the default types.
I have my class "Klass" already created:
VALUE rb_cKlass = rb_define_class("Klass", rb_cObject);
And how I wanted to check if the class is the good one:
VALUE my_function(VALUE self, VALUE my_argument) {
if(rb_check_class(my_argument), rb_cKlass)) {
// do something if my_argument is an instance of Klass
} else {
return Qnil;
}
}
Is there a way to do this?
I came across this recently, and used the RBASIC_CLASS macro, but was getting segfaults in certain scenarios for some unexplained reason.
After scanning through ruby.h, I found the CLASS_OF macro, which returns the class as VALUE of a given object.
VALUE obj = INT2NUM(10);
VALUE klass = CLASS_OF(obj); // rb_cInteger
Using Ruby 2.5
Every ruby object is internally represented by RObject struct (I will copy the source here for the sake of future readers):
struct RObject {
struct RBasic basic;
union {
struct {
uint32_t numiv;
VALUE *ivptr;
void *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */
} heap;
VALUE ary[ROBJECT_EMBED_LEN_MAX];
} as;
};
The very first member, RBasic, defines the class:
struct RBasic {
VALUE flags;
const VALUE klass;
}
To get an access to RBasic metadata of anything, one might use RBASIC macro:
RBASIC(my_argument)
To get the class directly, one might use RBASIC_CLASS macro:
RBASIC_CLASS(my_argument)
If you want to stay close to the is_a? Ruby fashion (i.e. check if any of the ancestors is the expected class), you could directly use the C implementation of is_a?, rb_obj_is_kind_of:
rb_obj_is_kind_of(my_argument, rb_cKlass) // Qtrue OR Qfalse
And since Qfalse == 0, you can just use that method as a condition:
VALUE my_function(VALUE self, VALUE my_argument) {
if(rb_obj_is_kind_of(my_argument, rb_cKlass)) {
// do something if my_argument is an instance of Klass
} else {
return Qnil;
}
}
To find this method, just check Object#is_a? documentation and click to toggle source, you'll see the C implementation if it is a C function (hence this will work for most of the standard lib).

String.withCString when the String is nil

The problem that'll be described relates to my previous question:
string.withCString and UnsafeMutablePointer(mutating: cstring) wrapped into a function which was my first approach to handle nil Strings (by putting withCString into a function)
and to a question which Mecki asked:
Why can't I pass an optional Swift String to C function that allows NULL pointers?
Imagine there is a c-function like:
unsigned long randomSign(char *pin, char *tag_signature, char *tag_data, char *xyz);
I know that the function works correctly if I wrap 4 string.withCString closures around the corresponding swift function:
// pin, tag_signature, tag_data and xyz are optional Strings so they may be nil which is a problem for my result.
// corresponding swift function:
// randomSign(pin: UnsafeMutablePointer<Int8>!, tag_signature: UnsafeMutablePointer<Int8>!, tag_data: UnsafeMutablePointer<Int8>!, xyz: UnsafeMutablePointer<Int8>!)
let result = pin.withCString { s1 in return
tag_signature.withCString {s2 in return
tag_data.withCString {s3 in return
xyz.withCString { s4 in return
randomSign(UnsafeMutablePointer(mutating: s1), UnsafeMutablePointer(mutating: s2), UnsafeMutablePointer(mutating: s3), UnsafeMutablePointer(mutating: s4))
}}}}
And so Martin R replied to an easier example, that it is not needed to wrap the closures around randomSign(arguments) and UnsafeMutablePointer(mutating: ...) because it can also take the strings and converts it.
But when I drop the closures and use it as Martin R described, it worked at the first launch on the simulator directly after starting the mac, but on consecutive calls of the randomSign-Function the return would tell me that for example the tag_signature or the pin would be invalid (but it actually is valid and I don't know why?!).
This leads me to the problem that I need the withCString closures (at the moment) but I have to handle nil-Strings, which would result the app to crash when it shall return the result because it couldn't evaluate the randomSign-Function.
So I tried to fit the approach below (also suggested by #Martin R) to Swift 3, but I did not workout to adapt it.
//Swift-2 written by Martin R
protocol CStringConvertible {
func withCString<Result>(#noescape f: UnsafePointer<Int8> throws -> Result) rethrows -> Result
}
extension String: CStringConvertible { }
extension Optional where Wrapped: CStringConvertible {
func withOptionalCString<Result>(#noescape f: UnsafePointer<Int8> -> Result) -> Result {
if let string = self {
return string.withCString(f)
} else {
return f(nil)
}
}
}
//Swift 3: ???
If anyone can tell me, why my function only works out when I use withCString but not when I dismiss it, I would be very grateful
and also if anyone knows how to solve the issue, i.e. correctly translating the swift-2 code to working swift-3 code.
The problem with
let result = randomSign(UnsafeMutablePointer(mutating: pin),
UnsafeMutablePointer(mutating: tag_signature),
UnsafeMutablePointer(mutating: tag_data),
UnsafeMutablePointer(mutating: xyz))
is that the temporary UTF-8 representation created from the Swift
strings is valid only during each call of UnsafeMutablePointer(),
but not necessarily still valid during the call of randomSign().
(So my final suggestion in https://stackoverflow.com/a/44027397/1187415
was actually not correct, I have updated that part).
A possible Swift 3 version of the wrapper in https://stackoverflow.com/a/39363769/1187415 is
extension Optional where Wrapped == String {
func withOptionalCString<Result>(_ f: (UnsafeMutablePointer<Int8>?) -> Result) -> Result {
if let string = self {
return string.withCString { f(UnsafeMutablePointer(mutating: $0)) }
} else {
return f(nil)
}
}
}
This handles both the optionality and casts the C string pointer
to a mutable pointer (as required by randomSign()). This can be
called as
let result = pin.withOptionalCString { s1 in
tag_signature.withOptionalCString { s2 in
tag_data.withOptionalCString { s3 in
xyz.withOptionalCString { s4 in
randomSign(s1, s2, s3, s4)
}
}
}
}
Remark: In theory, the problem can be avoided if the signature of randomSign() is changed to take const char * parameters:
unsigned long randomSign(const char *pin, const char *tag_signature, const char *tag_data, const char *xyz);
which one could then simply call as
let result = randomSign(pin, tag_signature, tag_data, xyz)
with optional or non-optional Swift strings.
However, this does currently not work, as reported in
SR-2814 Swift does not correctly pass in multiple optional strings to C function.

Factory flow. How does it work

Since I started to write code with AngularJS, I've been using factories and found them very useful.
I thought that they work like this (pseudo code):
FACTORY NAMESPACE {
PRIVATE FIELDS AND FUNCTIONS
RETURN {
INTERFACES TO ACCESS PRIVATE DATA
}
}
I thought that the expressions in return evaluates only when accessed directly, but, it seems that I didn't get it right.
I understand that the factories and services are very bottom of AngularJS and maybe someone thinks that this question shouldn't be here because it's trivial, and yet...
I created this plunk, I tried to find out why the variable changed inside factory code, won't keep its value after, when being accessed from outside, and what I found out confused me even more, the code inside of every return functions evaluates before anything else and it doesn't get called when it should be (by my logic)! Is. Is that designed that way, and if so, why?
Snippet from plnkr
var myApp = angular.module('app',[])
myApp.factory('_gl', [function () {
// Private fields
var _x;
function _somefunc(){
// This function evaluates even before the code of 'ctrl'
_x = 6;
console.log("changed:"+ _x);
}
return {
x:_x,
changeX:_somefunc()
}
}]);
myApp.controller('ctrl', ['_gl', function (_gl) {
_gl.x=2;
console.log("x init: " + _gl.x);
_gl.changeX(); // This does nothing at all
console.log("x after change: " + _gl.x);
}]);
/* Expected output
x init: 2
changed: 6
x after change:6
/*
/* Actual output
x init: 2
changed:6
x after change: 2
*/
Result:
After all that I found out from #dfsq (that right way is to use getters and setters), I came to the conclusion that although it can make some memory overhead, using simple JS global vars will do for me better.
the code inside of every return functions evaluates before anything else
Of course, because you are executing it with _somefunc().
It should be:
return {
x: _x,
changeX: _somefunc
}
Note, that there should be no () after _somefunc, which is invocation operator. You want changeX to be a reference to _somefunc, not result of _somefunc execution (_somefunc()).

Kotlin: For-loop must have an iterator method - is this a bug?

I have the following code:
public fun findSomeLikeThis(): ArrayList<T>? {
val result = Db4o.objectContainer()!!.queryByExample<T>(this as T) as Collection<T>
if (result == null) return null
return ArrayList(result)
}
If I call this like:
var list : ArrayList<Person>? = p1.findSomeLikeThis()
for (p2 in list) {
p2.delete()
p2.commit()
}
It would give me the error:
For-loop range must have an 'iterator()' method
Am I missing something here?
Your ArrayList is of nullable type. So, you have to resolve this. There are several options:
for (p2 in list.orEmpty()) { ... }
or
list?.let {
for (p2 in it) {
}
}
or you can just return an empty list
public fun findSomeLikeThis(): List<T> //Do you need mutable ArrayList here?
= (Db4o.objectContainer()!!.queryByExample<T>(this as T) as Collection<T>)?.toList().orEmpty()
try
for(p2 in 0 until list.count()) {
...
...
}
I also face this problem when I loop on some thing it is not an array.
Example
fun maximum(prices: Array<Int>){
val sortedPrices = prices.sort()
for(price in sortedPrices){ // it will display for-loop range must have iterator here (because `prices.sort` don't return Unit not Array)
}
}
This is different case to this question but hope it help
This can also happen in Android when you read from shared preferences and are getting a (potentially) nullable iterable object back like StringSet. Even when you provide a default, the compiler is not able to determine that the returned value will never actually be null. The only way I've found around this is by asserting that the returned expression is not null using !! operator, like this:
val prefs = PreferenceManager.getDefaultSharedPreferences(appContext)
val searches = prefs.getStringSet("saved_searches", setOf())!!
for (search in searches){
...
}

Defining setter return value

I just had a problem in one of my projects. Maybe I got the wrong concept about encapsulation.
Encapsulation protects member variables from classes, by defining getters and setters methods, now, i was reading that setters must be void, but in that case, how can I know if the function really set the value passed by argument. For example
void setArea(int a) {
if(a>0)
Area = a;
}
How can I be sure that argument "a" was a correct value, wouldnt be better defining the function like this
bool setArea(int a) {
if(a>0) {
Area = a;
return true;
}
return false;
}
Is that ok? that way i can know if a change really happened.
I think what you're looking for is a guard clause that throws an exception if invalid values are set:
void setArea(int a) {
if (a <= 0) throw new InvalidArgumentException(...);
Area = a;
}
But if you want client code to test for invalid values before setting them, you could have this:
bool isAreaValid(int a) {
return a > 0;
}
void setArea(int a) {
if (!isAreaValid(a)) throw new InvalidArgumentException(...);
Area = a;
}
Clients could be coded like this:
if (obj.isAreaValid(myArea)) {
obj.setArea(myArea);
}
But don't stop there. If the concept of area is important, spring it into existence into its own value object to make your design clearer.

Resources