I am playing with `DelimitedScope` to implement `o...
# arrow-contributors
k
I am playing with
DelimitedScope
to implement
option {}
continuation and I realised that
DelimContScope
can not manage
null
as a
shift
return value. the implementation already using nullable to show that the block is done. I replaced the nullable type with a quick GADT to represent empty state and allow nullable value:
Copy code
private val nextShift = atomic<Shift<(suspend () -> R)>>(Empty)
is there any better way to avoid constant boxing for the return values of shifts?
j
Yes, you could use a custom object and use any. Same principle as null just fixed to an internal. Still doesn't allow nesting but allows null
☝️ 1
πŸ‘ 2
I used null simply as convenience cause at the time of writing most of that package was experimental^^ also feel free to ask me if anything in there is unclear πŸ˜…
r
@kioba there will be an option continuation as well so this one should be named nullable for consistency
πŸ‘ 1
All computation expressions are now named after the data type decapitalized
k
sorry @Jannis didn’t mean to criticise, the implementation is super great πŸŽ‰ I have only a limited understanding of the DelimitedScope and don’t want to make any changes which could impact the performance on a bad way. @raulraja thanks, I will rename it πŸ‘ naming makes sense especially to have both of them πŸ™‚
j
@kioba no worries and please do criticise^^ What I meant was more along the lines of "everything is pretty hacky and not all that well tested so any improvement or found bug is great!" anyway πŸ™ˆ Either way, the atomic containing the result needs to allow nullables to work properly in a generic setting. Best is probably a singleton object for which we check with reference equality since we don't need to be concerned with nesting here.
k
you mean a separate atomic variable l to keep track of the end of the block?
create a draft PR to be able to show the current implementation. https://github.com/arrow-kt/arrow-core/pull/251 Added a few questions regarding the code arrangement but happy to take any feedback regarding these changes if you have time πŸ™‚ πŸ‘Œ
πŸ‘ 1
s
@kioba this is the trick @Jannis is referring to. It's comming in a lot of Kotlin generic code when not using
Option
to optimise over allocations in hot-spot areas like this. It sadly requires
Any?
and thus also casting in some places.
Copy code
private object MY_NULL

class Generic<T>(val value: T) {

    val atomicValue: Any? = value

    fun isMyNull(): Boolean =
        atomicValue === MY_NULL
}
😲 1
☝️ 2
k
this is definitely a neat trick! Reminds me the old days for C++ boolean bitwise πŸ˜…. thanks guys for teaching this πŸ‘¨β€πŸŽ“ I will go and apply the changes today πŸ‘
πŸ™Œ 1
s
No problem, it's a bit dirty but a good way to optimise low-level code to support generic
?
πŸ™‚
j
It has the same nesting problems as nullables but since it uses a different reference it doesn't lead to nested null cases^^ Sadly we can't do this in general for option because of those drawbacks
πŸ‘ 2