https://kotlinlang.org logo
Channels
100daysofcode
100daysofkotlin
100daysofkotlin-2021
advent-of-code
aem
ai
alexa
algeria
algolialibraries
amsterdam
android
android-architecture
android-databinding
android-studio
androidgithubprojects
androidthings
androidx
androidx-xprocessing
anime
anko
announcements
apollo-kotlin
appintro
arabic
argentina
arkenv
arksemdevteam
armenia
arrow
arrow-contributors
arrow-meta
ass
atlanta
atm17
atrium
austin
australia
austria
awesome-kotlin
ballast
bangladesh
barcelona
bayarea
bazel
beepiz-libraries
belgium
benchmarks
berlin
big-data
books
boston
brazil
brikk
budapest
build
build-tools
bulgaria
bydgoszcz
cambodia
canada
carrat
carrat-dev
carrat-feed
chicago
chile
china
chucker
cincinnati-user-group
cli
clikt
cloudfoundry
cn
cobalt
code-coverage
codeforces
codemash-precompiler
codereview
codingame
codingconventions
coimbatore
collaborations
colombia
colorado
communities
competitive-programming
competitivecoding
compiler
compose
compose-android
compose-desktop
compose-hiring
compose-ios
compose-mp
compose-ui-showcase
compose-wear
compose-web
confetti
connect-audit-events
corda
cork
coroutines
couchbase
coursera
croatia
cryptography
cscenter-course-2016
cucumber-bdd
cyprus
czech
dagger
data2viz
databinding
datascience
dckotlin
debugging
decompose
decouple
denmark
deprecated
detekt
detekt-hint
dev-core
dfw
docs-revamped
dokka
domain-driven-design
doodle
dsl
dublin
dutch
eap
eclipse
ecuador
edinburgh
education
effective-kotlin
effectivekotlin
emacs
embedded-kotlin
estatik
event21-community-content
events
exposed
failgood
fb-internal-demo
feed
firebase
flow
fluid-libraries
forkhandles
forum
fosdem
fp-in-kotlin
framework-elide
freenode
french
fritz2
fuchsia
functional
funktionale
gamedev
ge-kotlin
general-advice
georgia
geospatial
german-lang
getting-started
github-workflows-kt
glance
godot-kotlin
google-io
gradle
graphic
graphkool
graphql
graphql-kotlin
graviton-browser
greece
grpc
gsoc
gui
hackathons
hacktoberfest
hamburg
hamkrest
helios
helsinki
hexagon
hibernate
hikari-cp
hire-me
hiring
hongkong
hoplite
http4k
hungary
hyderabad
image-processing
india
indonesia
inkremental
intellij
intellij-plugins
intellij-tricks
internships
introduce-yourself
io
ios
iran
israel
istanbulcoders
italian
jackson-kotlin
jadx
japanese
jasync-sql
java-to-kotlin-refactoring
javadevelopers
javafx
javalin
javascript
jdbi
jhipster-kotlin
jobsworldwide
jpa
jshdq
juul-libraries
jvm-ir-backend-feedback
jxadapter
k2-early-adopters
kaal
kafka
kakao
kalasim
kapt
karachi
karg
karlsruhe
kash_shell
kaskade
kbuild
kdbc
kgen-doc-tools
kgraphql
kinta
klaxon
klock
kloudformation
kmdc
kmm-español
kmongo
knbt
knote
koalaql
koans
kobalt
kobweb
kodein
kodex
kohesive
koin
koin-dev
komapper
kondor-json
kong
kontent
kontributors
korau
korean
korge
korim
korio
korlibs
korte
kotest
kotest-contributors
kotless
kotlick
kotlin-asia
kotlin-beam
kotlin-by-example
kotlin-csv
kotlin-data-storage
kotlin-foundation
kotlin-fuel
kotlin-in-action
kotlin-inject
kotlin-latam
kotlin-logging
kotlin-multiplatform-contest
kotlin-mumbai
kotlin-native
kotlin-pakistan
kotlin-plugin
kotlin-pune
kotlin-roadmap
kotlin-samples
kotlin-sap
kotlin-serbia
kotlin-spark
kotlin-szeged
kotlin-website
kotlinacademy
kotlinbot
kotlinconf
kotlindl
kotlinforbeginners
kotlingforbeginners
kotlinlondon
kotlinmad
kotlinprogrammers
kotlinsu
kotlintest
kotlintest-devs
kotlintlv
kotlinultimatechallenge
kotlinx-datetime
kotlinx-files
kotlinx-html
kotrix
kotson
kovenant
kprompt
kraph
krawler
kroto-plus
ksp
ktcc
ktfmt
ktlint
ktor
ktp
kubed
kug-leads
kug-torino
kvision
kweb
lambdaworld_cadiz
lanark
language-evolution
language-proposals
latvia
leakcanary
leedskotlinusergroup
lets-have-fun
libgdx
libkgd
library-development
lincheck
linkeddata
lithuania
london
losangeles
lottie
love
lychee
macedonia
machinelearningbawas
madrid
malaysia
mathematics
meetkotlin
memes
meta
metro-detroit
mexico
miami
micronaut
minnesota
minutest
mirror
mockk
moko
moldova
monsterpuzzle
montreal
moonbean
morocco
motionlayout
mpapt
mu
multiplatform
mumbai
munich
mvikotlin
mvrx
myndocs-oauth2-server
naming
navigation-architecture-component
nepal
new-mexico
new-zealand
newname
nigeria
nodejs
norway
npm-publish
nyc
oceania
ohio-kotlin-users
oldenburg
oolong
opensource
orbit-mvi
osgi
otpisani
package-search
pakistan
panamá
pattern-matching
pbandk
pdx
peru
philippines
phoenix
pinoy
pocketgitclient
polish
popkorn
portugal
practical-functional-programming
proguard
prozis-android-backup
pyhsikal
python
python-contributors
quasar
random
re
react
reaktive
realm
realworldkotlin
reductor
reduks
redux
redux-kotlin
refactoring-to-kotlin
reflect
refreshversions
reports
result
rethink
revolver
rhein-main
rocksdb
romania
room
rpi-pico
rsocket
russian
russian_feed
russian-kotlinasfirst
rx
rxjava
san-diego
science
scotland
scrcast
scrimage
script
scripting
seattle
serialization
server
sg-user-group
singapore
skia-wasm-interop-temp
skrape-it
slovak
snake
sofl-user-group
southafrica
spacemacs
spain
spanish
speaking
spek
spin
splitties
spotify-mobius
spring
spring-security
squarelibraries
stackoverflow
stacks
stayhungrystayfoolish
stdlib
stlouis
strife-discord-lib
strikt
students
stuttgart
sudan
swagger-gradle-codegen
swarm
sweden
swing
swiss-user-group
switzerland
talking-kotlin
tallinn
tampa
teamcity
tegal
tempe
tensorflow
terminal
test
testing
testtestest
texas
tgbotapi
thailand
tornadofx
touchlab-tools
training
tricity-kotlin-user-group
trójmiasto
truth
tunisia
turkey
turkiye
twitter-feed
uae
udacityindia
uk
ukrainian
uniflow
unkonf
uruguay
utah
uuid
vancouver
vankotlin
vertx
videos
vienna
vietnam
vim
vkug
vuejs
web-mpp
webassembly
webrtc
wimix_sentry
wwdc
zircon
Powered by
Title
s

Smallville7123

04/18/2019, 5:35 AM
R
represents a
kotlin.function
right? thus
fun a(R) {
    R.invoke()
}
will take a function accepting 0 parameters, then execute that function right?
g

gildor

04/18/2019, 5:39 AM
what is that? It is invalid syntax
☝️ 1
s

Smallville7123

04/18/2019, 5:39 AM
idk
kotlin.Function
kotlin.Function(R) is the unified supertype of all function types. It is parame-
terized over function return type R.
g

gildor

04/18/2019, 5:40 AM
if you want to pass function with 0 arguments you need something like this:
fun a(r: () -> Unit) {
   r()
}
Is that error message?
s

Smallville7123

04/18/2019, 5:40 AM
kotlin language spec
g

gildor

04/18/2019, 5:41 AM
ah, I see
s

Smallville7123

04/18/2019, 5:41 AM
Kotlin/Core>Type system>Type kinds>Built-in types>kotlin.function
im trying to learn how to construct functions similar to .any, .let, and .also
g

gildor

04/18/2019, 5:42 AM
I’m not familiar with this notation, but according to context,
R
is return type of function
Why do you need language specification for this?
let, any and also just simple stdlib function
s

Smallville7123

04/18/2019, 5:43 AM
cus i cant find anything usefull in the docs
g

gildor

04/18/2019, 5:43 AM
not a part of the language
Just open source code
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}
Or, essentially, if you remove inline and contract declaration it’s just:
fun <T, R> T.let(block: (T) -> R): R {
    return block(this)
}
s

Smallville7123

04/18/2019, 5:45 AM
has no idea what that means
g

gildor

04/18/2019, 5:45 AM
you have no idea how to declare a function?
s

Smallville7123

04/18/2019, 5:46 AM
no, the
<T, R> T.let(block: (T) -> R): R
part
g

gildor

04/18/2019, 5:46 AM
Maybe you should start from the langauge documentation reading, not from language specification
t

thana

04/18/2019, 5:46 AM
reading the kotlin language spec, but cannot even read kotlin?!
g

gildor

04/18/2019, 5:46 AM
do you know what is generic?
s

Smallville7123

04/18/2019, 5:47 AM
T
?
I would really recommend you first read about basic syntax and basic concepts used in the language
❤️ 1
except generics, please read about extension functions, which is used in `let`: https://kotlinlang.org/docs/reference/extensions.html
s

Smallville7123

04/18/2019, 5:59 AM
how do i write an extention function that correctly supports non nullable and nullable types
as
fun String?.toStack(): Stack<String>? {
    if (this == null) return null
    val deq = Stack<String>()
    var i = 0
    while (i < this.length) deq.addLast(this[i++].toString())
    return deq
}
ALWAYS returns
String?
regardless if it is called from a function returning
String
or
String?
g

gildor

04/18/2019, 6:04 AM
This function doesn’t return
String?
it returns
Stack<String>?
s

Smallville7123

04/18/2019, 6:05 AM
would i need seperate extentions for each type? eg
/**
 * converts a [String] into a [Stack]
 * @see Stack.toStringConcat
 * @return the resulting conversion
 */
fun String.toStack(): Stack<String> {
    val deq = Stack<String>()
    var i = 0
    while (i < this.length) deq.addLast(this[i++].toString())
    return deq
}

/**
 * converts a [String] into a [Stack]
 * @see Stack.toStringConcat
 * @return the resulting conversion
 */
fun String?.toStack(): Stack<String>? { 
    if (this == null) return null
    return this.toStack()
}
so it can be called on both
val a: String = "a"
val b: String? = "a"
a.toStack()
b.toStack()
and return the nullable or non-nullable types respectively
g

gildor

04/18/2019, 6:05 AM
No, you don’t need
I see what you mean
s

Smallville7123

04/18/2019, 6:07 AM
as with only the
String?.toStack
it returns a Stack<String>? when called on a
String
type in which a nullable should not be returned
g

gildor

04/18/2019, 6:08 AM
no, you cannot change return type like that depending on receiver nullability, you need 2 functions
But I don’t see reason for that, why not just have non-nullable version only:
fun String.toStack(): Stack<String> {
    val deq = Stack<String>()
    var i = 0
    while (i < this.length) deq.addLast(this[i++].toString())
    return deq
}
val a: String = "a"
val b: String? = "a"
a.toStack()
b?.toStack()
s

Smallville7123

04/18/2019, 6:10 AM
Type mismatch: inferred type is Stack<String>? but Stack<String> was expected
g

gildor

04/18/2019, 6:10 AM
as I understand it has now the same semantics as your original idea
Do you see safe call operator on
b
? Just use it to call toStack() only if b is non-null
t

thana

04/18/2019, 6:12 AM
g

gildor

04/18/2019, 6:16 AM
See isn’t what you need? https://pl.kotl.in/whlrJtHIJ
s

Smallville7123

04/18/2019, 6:24 AM
how do i pass a vararg to a vararg
g

gildor

04/18/2019, 6:24 AM
How this related to this thread?
try ask in #getting-started
also you can check documentation
what does
<T, R>
mean
and how does that differ from
<T>
t

thana

04/18/2019, 6:38 AM
so you did NOT read the documentation you were pointed to. youre a hopeless case
s

Smallville7123

04/18/2019, 6:41 AM
i did
T
is a type parameter
g

gildor

04/18/2019, 6:42 AM
See, how you can define type parameter of function?
T is just a name
it maybe any other letter or word
tYpe_PARAmeter
is also completely valid generic identifier
R is just a conventional name for generic return type
But again, even if you don’t know this convention, it’s completely clear how this R is used
s

Smallville7123

04/18/2019, 6:44 AM
so how does
R
differ from
T
, cant you just cast the return
as T
?
g

gildor

04/18/2019, 6:44 AM
T
differs from
R
because it’s different type that in case of
let
used as type of return value
s

Smallville7123

04/18/2019, 6:46 AM
R
IS mentioned in https://kotlinlang.org/docs/reference/lambdas.html but it is not very informative
g

gildor

04/18/2019, 6:46 AM
R is just a name
it’s just a name of generic
s

Smallville7123

04/18/2019, 6:47 AM
as it literally just states
In the code above, the parameter combine has a function type (R, T) -> R, so it accepts a function that takes two arguments of types R and T and returns a value of type R. It is invoked inside the for-loop, and the return value is then assigned to accumulator.
g

gildor

04/18/2019, 6:47 AM
If you really don’t understand documentation, I will try to explain
let
declaration for you
fun
- keyword that mens that we declare a function
<T, R>
- declare that this function has two generic parameters, one with name
T
, another with name
R
. Names by themselves mean nothing, but there is common convention that main type is T and return type is R
T.
- this prefix with dot before function name means that this is extension function, and this is extension function for T, so in this case (because T doesn’t declare any specific type) means that this function maybe applied to any type, including nullable, this type will be inferred on call site
let
- name of this function
(block: (T) -> R)
- declare argument of this function, where:
block
- name of argument
(T) -> R
- Type of argument, this is function type - https://kotlinlang.org/docs/reference/lambdas.html#function-types, it means any function with 1 parameter of type T and return type R, T and R maybe any in this case, they just should be the same as receiver and return type of this function, this is why generic types declaration is required, we specify which generic types will be used.
: R
- return type of this function, function returns generic type R, the same type that
block
returned
s

Smallville7123

04/18/2019, 6:54 AM
as i know that <T> is whatever type that the function is specified as, in the case of
fun <T> retz(n:T): T {
    return n as T // valid as it returns the input of whatever it is given
}

fun <T> retz(): T {
    return 0 as T // this is invalid
}

fun a() {
    val x = retz<Int>()
    var y : Int = retz(0)
}
the type is inferred from the context in the case of
y
, and specified explicitly in the case of
x
g

gildor

04/18/2019, 6:55 AM
yes, type is inferred in this case, but you also can specify it explicitly
s

Smallville7123

04/18/2019, 7:00 AM
and in the case of
fun <T> T.retz(): T {
    return this // returns itself
}

fun b() {
    var x = 5
    x = x.retz()
}
retz returns what ever it is invoked from as the type of whatever it is invoked from
g

gildor

04/18/2019, 7:01 AM
I know how generics work, what is your question tho?
s

Smallville7123

04/18/2019, 7:02 AM
how does adding
R
to it change how it works
for example,
fun <T, R> T.retzR(): R {
    return this as R // returns itself
}
isnt it the same as
fun <T> T.retz(): T {
    return this // returns itself
}
?
g

gildor

04/18/2019, 7:04 AM
Type will be different
this as R
This of course doesn’t make any sense
your examples just do nothing useful
so they don’t have cases for additional generic param
s

Smallville7123

04/18/2019, 7:05 AM
well it has a return type of
R
, and
this
is of type
T
and
R
itself is not an expression
g

gildor

04/18/2019, 7:05 AM
of course, R is not expression, same as T, it’s type!
see, your problem because you don’t have any good example
s

Smallville7123

04/18/2019, 7:05 AM
so how do i use
R
g

gildor

04/18/2019, 7:06 AM
let’s do another example, function where you pass 2 params and it return Pair with them inside?
fun <A, B> createPair(a: A, b: B): Pair<A,B> {
   return Pair(a, b)
}
do you see now how additional type param is useful?
s

Smallville7123

04/18/2019, 7:07 AM
no
g

gildor

04/18/2019, 7:07 AM
so now you can just call: and get return type:
val pair: Pair<Int, String> = createPair(1, "A")
¯\_(ツ)_/¯
s

Smallville7123

04/18/2019, 7:08 AM
why not just do
T, T
?
g

gildor

04/18/2019, 7:09 AM
Because than it would be impossible to call with different type
see
s

Smallville7123

04/18/2019, 7:09 AM
wait wtf how are types
A
and
B
valid o.o
g

gildor

04/18/2019, 7:09 AM
fun <T> createPair(a: T, b: T): Pair<T, T> {
   return Pair(a, b)
}
now try to use this function with:
createPair(1, "A")
and see what will happend
wait wtf how are types
A
and
B
valid o.o
YES! This is what I told you at least 5 times in this thread, that geneic name is just NAME
It can be:
<LetterA, Generic_B>
same valid, just against name convention
s

Smallville7123

04/18/2019, 7:10 AM
ok
so they are basically like macros?
eg <TYPE> and all occurences of TYPE is replaced with whatever value is passed to TYPE? for example
f<Int>
all of TYPE is replaced by
Int
and
f("h")
all of TYPE is replaced by
String
as inferred from the context
thus a completely valid declaration can be
fun <a, b> f(var0 : c, var1 : d): e) {
    val var2 = var0.toInt()
    val var3 = var1.toString()
    println("var2 = $var2\nvar3 = $var3")
    return 0 // not sure if this is valid
}

val x = f<Int, String>("0", 5)
?
g

gildor

04/18/2019, 7:21 AM
no, it’s invalid
because
c
and
d
are not defined
what is c and d?
same for
e
s

Smallville7123

04/18/2019, 7:23 AM
so the replacement only applies to names inside of <> ?
g

gildor

04/18/2019, 7:24 AM
no
this is not “replacement”
this is just generic syntax
you say to compiler “I have generic types a and b”, so compiler will resolve it, but if you do not specify generic param names, compiler will try to resolve it as some other type, like in your case
c
is not declared, and compiler tries to resolve it as some existing type of class
c
which doesn’t exist
so they are basically like macros?
No, generics are not like macros, they like templates in C++, or I don’t know which langauges are more familiar for you Try to read something about generics, about JVM generics, use cases and implementation details, maybe than you will realize that you don’t need preprocessor for Kotlin
s

Smallville7123

04/18/2019, 7:28 AM
ok
so in
fun <T, R> T.let(block: (T) -> R): R {
    return block(this)
}
if called in
val x = 0; x.let {}
what does
R
recieve?
as
T
recieves the type
Int
thus
R
cannot recieve a type as
0
only has one type, and
T
has already recieved the one type
unless the input in which it is invoked has two types, such as a Pair
eg
Pair<Int, String>().let {}
in which
T
recieves
Int
and
R
recieves
String
s

SiebelsTim

04/18/2019, 7:34 AM
I wish I had the patience you have @gildor
🤗 1
1
s

Smallville7123

04/18/2019, 7:35 AM
in which case
let
must return a
String
g

gildor

04/18/2019, 7:37 AM
See let source code
R is type returned from lambda that you passed as param
If you just write this code in IDE it will perfectly show you all types and you can see that your assumption about this code is wrong
Pair<Int, String>().let {}
T will have type Pair<Int, String>
because your lambda is empty it implicitly means that lambda return
Unit
, so return type of let will be
Unit
val x = 0; x.let {}
what does
R
recieve?
@Smallville7123 do you use IDE?
s

Smallville7123

04/18/2019, 7:40 AM
yes
g

gildor

04/18/2019, 7:40 AM
Which one?
s

Smallville7123

04/18/2019, 7:40 AM
IntelliJ Idea
g

gildor

04/18/2019, 7:41 AM
okay, than write this code and check types
val x = 0; 
val y = x.let {}
there are few ways to get expression type hints, action View -> Type Info or intent “Specify type explicitly”
s

Smallville7123

04/18/2019, 7:43 AM
so T gets passed whatever type is returned from the T that it is invoked on?
for example,
0.toString().let {}
will have
T
as
String
and not
Int
as
toString()
returns
String
?
g

gildor

04/18/2019, 7:44 AM
Sure, it will have T inferred to String
yes
s

Smallville7123

04/18/2019, 7:44 AM
ok
so
(0 is Int).let {}
will get passed the return type of
Boolean
as
T
and
it
will get passed the return value ?
g

gildor

04/18/2019, 7:52 AM
it` will get passed the return value?
What do you mean?
Return type is again Unit, because you return nothing
s

Smallville7123

04/18/2019, 7:53 AM
like...
it
will either contain the value
true
or
false
depending on what the expression evaluates to (in this case
(0 is Int)
evaluates to true)
g

gildor

04/18/2019, 7:53 AM
yes
it’s correct
and type Boolean
s

Smallville7123

04/18/2019, 7:54 AM
as inferred by the return value? or as specified by the return type?
im assuming it is specified by the return type, as if a function returns null, and is nullable, it will become
null : Nothing?
instead of say
null : String?
though
it
is non modifiable so it would not matter right?
imma just assume it is inferred from the return type just to be safe
anyway
s

SiebelsTim

04/18/2019, 8:03 AM
The type of the expression before let will be the T of let, yes.
g

gildor

04/18/2019, 8:08 AM
as inferred by the return value? or as specified by the return type?
It will infer it from type that returned from let lambda body:
"some".let {} // R to Unit
"some".let { it } // R to String
"42".let { it.toInt() } // R to Int
s

Smallville7123

04/18/2019, 8:15 AM
ok
how can i make a lambda function accept an
it
paramater
1
as
fun <T> T.ifTrue(i:Boolean, Block: (i:T) -> T): Boolean {
    if (i) {
        Block()
    }
    return i
}
sais
No value passed for parameter 'p1'
for
Block()
g

gildor

04/18/2019, 9:44 AM
you have to pass param to
Block()
like
Block(this)
s

Smallville7123

04/18/2019, 9:45 AM
it should work like this
fun x() {
    val x = "a"
    val y = x.ifTrue(x.startsWith('a')) {
        it.get(0)
    }
    println("y = $y")
}
g

gildor

04/18/2019, 9:46 AM
this function block, as I understand, should receive receiver
so
it
shouldbe T
But what function should return? also T?
Now you return Boolean
s

Smallville7123

04/18/2019, 9:48 AM
if i do that i get
Type inference failed: Cannot infer type parameter T in fun  T.ifTrue(i: Boolean, Block: (ii: T) -> T): Boolean None of the following substitutions receiver: Comparable*> arguments: (Boolean,(Comparable*>) -> Comparable*>) receiver: String arguments: (Boolean,(String) -> String) can be applied to receiver: String arguments: (Boolean,(String) -> Char)
for
val y = x.ifTrue(x.startsWith('a')) {
g

gildor

04/18/2019, 9:49 AM
again, I don’t understand how this function should work
return true looks strange for me
have
(ii: T) -> T)
also looks strange
s

Smallville7123

04/18/2019, 9:49 AM
fun <T> T.ifTrue(i:Boolean, Block: (ii:T) -> T): Boolean {
    if (i) {
        Block(this)
    }
    return i
}

fun x() {
    val x = "a"
    val y = x.ifTrue(x.startsWith('a')) {
        it.get(0)
    }
    println("y = $y")
}
g

gildor

04/18/2019, 9:50 AM
why do you need lambda if you do not use result
s

Smallville7123

04/18/2019, 9:51 AM
fk im thinking of the other use case
g

gildor

04/18/2019, 9:51 AM
This code doesn’t work, because your lambda return type is wrong
it.get(0)
returns Char
which is against your function declaraion that should return String, the same type as T, receiver
s

Smallville7123

04/18/2019, 9:52 AM
fun <T> T.ifTrue(i:Boolean, Block: (ii:T) -> T): T {
    if (i) {
        return Block(this)
    }
    return this
}

fun x() {
    val x = "a"
    val y = x.ifTrue(x.startsWith('a')) {
        it.length.toString()
    }
    println("y = $y")
}
g

gildor

04/18/2019, 9:53 AM
Yes, this is valid, but doesn’t make any sense, because
it.length.toString()
is never used
Oh, sorry, I see that you also changed Block type
Yes, this will work
s

Smallville7123

04/18/2019, 10:08 AM
how do i get it to work like the generic
also
,
let
and others do
g

gildor

04/18/2019, 10:08 AM
But this particular function looks redundand, it’s exactly the same as:
if (x.startsWith('a')) {
        x.length.toString()
    } else {
        x
    }
or even:
if (x.startsWith('a')) x.length.toString() else x
how do i get it to work like the generic
also
,
let
and others do
What do you mean? What kind function do you want to write?
s

Smallville7123

04/18/2019, 10:09 AM
as for
val yx = x.ifTrueReturn(x.startsWith('a')) {
        x = it.drop(1)
    }
i get
Expected a value of type String
for
x = it.drop(1)
when
x.also {
        x = it.drop(1)
    }
does not give that error
g

gildor

04/18/2019, 10:10 AM
Because your lambda return value,
also
lambda doesn’t return anything
Maybe you need something like this
fun <T> T.ifTrue(i:Boolean, Block: (ii:T) -> Unit): T {
    if (i) {
        Block(this)
    }
    return this
}
s

Smallville7123

04/18/2019, 10:11 AM
so i would need to change it to
Block2: (T) -> Unit
?
g

gildor

04/18/2019, 10:11 AM
yes
s

Smallville7123

04/18/2019, 10:11 AM
ok
g

gildor

04/18/2019, 10:11 AM
first I would just tried to explain it what is your goal for this function
because this is really strange code that doesn’t make a lot of sense
I mean if you use those changes and apply them here
val x = "a"
    val y = x.ifTrue(x.startsWith('a')) {
        it.length.toString()
    }
    println("y = $y")
x and y will be the same,
it.length.toString()
never used
so it will be completely broken
s

Smallville7123

04/18/2019, 10:13 AM
sorry, i have two versions of my 2 cases
@file:Suppress("unused")
fun <T> T.ifTrue(i:Boolean, Block: (ii:T) -> T): T {
    if (i) {
        return Block(this)
    }
    return this
}

fun <T> T.ifTrueReturn(ii:Boolean, Block2: (T) -> Unit): Boolean {
    if (ii) {
        Block2(this as T)
    }
    return ii
}

fun main() {
    var x = "abc"
    println("x = $x") // x = abc
    var y = x.ifTrue(x.startsWith('a')) {
        it.length.toString()
    }
    println("y = $y") // y = 3
    println("x = $x") // x = abc
    val yx = x.ifTrueReturn(x.startsWith('a')) {
        x = it.drop(1)
    }
    println("yx = $yx") // yx = true
    println("x = $x") // x = abc // should be "bc"
}
as otherwise i get overload conflicts
the main use case is
ifTrueReturn
, as the
ifTrue
can be simplified with,
val y = if(x.startsWith('a')) { x.length.toString() } else x
anyway, is it possible to get
it
to modify the value of what ever it is invoked from, so i dont need to do
x = it...
when
x == it
g

gildor

04/18/2019, 10:20 AM
please, share your snippets with http://play.kotlinlang.org
I don’t think that this is simplification
s

Smallville7123

04/18/2019, 10:22 AM
g

gildor

04/18/2019, 10:23 AM
i want “it” to modify “x” itself
It’s impossible, strings are immutable
only way is return new string
you probably need this: https://pl.kotl.in/wUK4OvMQb
or just reassign x
s

Smallville7123

04/18/2019, 10:37 AM
ok ;-;
s

snowe

04/18/2019, 2:27 PM
wow. the patience in this thread is astounding. 200 comments geez.
👆 1
s

Smallville7123

04/18/2019, 8:48 PM
how can i change
fun <T> T.ifTrueReturn(ii:Boolean, Block2: (T) -> Unit): Boolean {
    if (ii) Block2(this)
    return ii
}
so that i can chain call it with a previous
fun <T> T.ifUnconditionalReturn(ii:Boolean, Block2: (T) -> Unit): Boolean {
    Block2(this)
    return ii
}
call for example
it.alias != null -> when {
    ifUnconditionalReturn(it.alias.equals(command) && !it.command.equals(command)) {
        println("alias found")
    }
        .ifTrueReturn { println("and it matches $command") }
        .ifFalseReturn { println("and it does not match $command") } -> {
        val t = get(it.command!!)
        if (t != null) return t
    }
}
which is basically
ifUnconditionalReturn(BOOLEAN_EXPRESSION) {CODE_TO_EXECUTE}.ifTrueReturn/*returns BOOLEAN_EXPRESSION*/{CODE_TO_EXECUTE}.ifFalseReturn/*returns BOOLEAN_EXPRESSION*/{CODE_TO_EXECUTE}
or
ifUnconditionalReturn() {
}.ifTrueReturn {
}.ifFalseReturn {
}
wait this would work right?
fun <T> Boolean.ifTrueReturn(Block2: () -> Unit): Boolean {
    if (this) Block2()
    return this
}
if so why do i get
Type inference failed: Not enough information to infer parameter T in fun <T> Boolean.ifTrueReturn(Block2: () -> Unit): Boolean
Please specify it explicitly.
is it because i have <T> which is unused?
is
fun <T, R> T.executeIfTrue(ii:Boolean, code: (ii:T) -> R): R = ifTrue(ii) { code(this) }
the correct way to alias
fun <T, R> T.ifTrue(ii:Boolean, code: (ii:T) -> R): R = if (ii) code(this) else this as R
g

gildor

04/18/2019, 11:20 PM
Never use explicit cast, if you don't know what you do, and in this case you force compiler to shut up, but it's just wrong