SlideShare a Scribd company logo
1 of 36
KOTLIN
GETS
REFLECTION
Andrey.Breslav@JetBrains.com
Introspection is examination of
one's own conscious thoughts
and feelings.
Schultz, D. P.; Schultz, S. E. (2012).
A history of modern psychology (10th ed.)
LEGAL
Takeiteasy
DON’T JUDGE
STRICTLY
OUTLINE
• Intro
• Ways of Introspection
• Reflection API
• Reflection Literals
• Expression Trees
• Conclusion
USE CASES
Dependency Injection
Data binding
Convention over
configuration
Hacks
Workarounds
Black Magic
INTROSPECTION
Instances
- what is your class?
Classes & Types
- what are your members? supertypes? create an instance
Methods/Fields
- what are your parameters/types/etc? run with these args.
Expressions
- ???
JAVA.LANG.REFLECT?
Top-level functions
Default arguments
Properties
Nullable types
Special types (Nothing, (Mutable)List, etc)
…
+ modules (classes in a package)
METADATA
*.kt
*.class
(kotlin)
*.jar
(kotlin)
kotlin
symbols
kotlin
symbols
kotlin
symbols
java
symbols
kotlinc
HOW TO STORE
METADATA?
*.class
Custom
attributes
Annotations
Annotate each
symbol
One big
annotation
ONE BIG ANNOTATION
*.class
@KotlinClass(“data”)
val/var types defaults …
Java definitions
erased generic annotations …
RE-USE
j.l.Class
*.kt
*.class
AST
@KotlinClass
Symbols
DISCREPANCY 1
java.lang.annotation.Annotation
vs
org.jetbrains.kotlin.internal….AnnotationDescriptor
PURE JAVA CLASSES?
j.l.Class
*.kt
*.class
AST
@KotlinClass
Symbols
*.java
java2k
DISCREPANCY 2
// Java
class Foo {
@NotNull
String getFirstName() { … }
String getMiddleName() { … }
}
// Corresponding Kotlin
class Foo {
fun getFirstName(): String
fun getMiddleName(): String?
}
DISCREPANCY 2
j.l.Class
*.class Symbols
*.java
java2k
annotations.xml
SUMMARY 1
Kotlin-specific reflection API
- works for Java as well
Metadata representation
- one big annotation
- re-use code from the compiler
Problems
- representing annotations
- nullable/mutable types
ENTRY
POINTS
SYNTAX (TENTATIVE)
Foo::class
expr::class
List<String>::member
org.sample.bar::member
expr::member
expr::type (maybe)
USE CASES:
PASSING CODE AROUND
list.filter(Item::isValid)
* Why not a lambda?
foo {a, b, c -> bar(a, b, c) }
USE CASES:
CONSTRUCTORS
fun <T: Tag> tag(
create: () -> T, init: T.() -> Unit
) { … }
tag(::DIV) { // kara.tags::DIV
…
}
USE CASES:
DATA BINDING
class Model {
var userName: String by observable()
}
bind(view.textField, model::userName)
GENERICS?
fun foo(s: String): Foo
::foo : (String) -> Foo
fun <T> foo(t: T): T { … }
::foo : ∀T.(T) -> T
RANK-2
POLYMORPHISM
interface Function1<P1, R> {
R invoke(P1 p1);
}
vs
interface GenericFunction1_1<P1, R> {
<T> R<T> invoke(P1<T> p1);
}
ENCODING FOR
FUNCTIONS
f: (Foo) -> Bar is Function1<Foo, Bar>
interface Function1<P1, R> {
R invoke(P1 p1);
}
GENERIC FUNCTIONS
f: <T>(List<T>) -> T
• GenericFunction<List<T>, T> ???
• GenericFunction<T, List<T>, T> ???
interface GenericFunction1_1<P1, R> {
<T> R<T> invoke(P1<T> p1);
}
+ Kinds
GENERICS
class Foo<T> {
fun <R> bar(t: T): R { … }
}
Foo<T’>::bar<R’> : (T’) -> R’
EXPR::TYPE
val x: Any = listOf(1, 2, 3)
x::class -> java.util.ArrayList
x::type -> java.util.ArrayList<Unknown>
vs
val x = listOf(1, 2, 3) // x: List<Int>
x::class -> java.util.ArrayList
x::type -> java.util.ArrayList<Int>
DELEGATED
PROPERTIES
val foos: List<Foo> by Lazy { foos.find(…) }
class Lazy<T>(compute: () -> T) {
private var value: T? = null
fun get(me: Any, p: PropertyMetadata): T {
if (value == null) value = compute()
return value
}
}
DELEGATED
PROPERTIES
val foos: List<Foo> by Lazy { foos.find(…) }
::foos::delegate : Lazy<Foo>
::foos : Property<List<Foo>>
or
::foos.delegate : Lazy<Foo>
::foos : DelegatedProperty<
List<Foo>,
Lazy<Foo>
>
SUMMARY 2
Reflection literals
- Static name lookup & typing
- Generics are hard, as usual
CODE
INTROSPECTION
I told you!
USE CASES: LINQ
db
.selectFrom(::User)
.where { lastName.startsWith(“A”) }
.orderBy { lastName + firstName }
server
client
server
USE CASES: WEB
html {
body {
onLoad {
...
}
...
}
}
EXPRESSION TREES
fun onLoad(ast: Expression<() -> Unit>) {
...
}
onLoad {
... // compiled to factory calls
}
At run time the tree can be translated to JS
SUMMARY
Kotlin’s introspection facilities
- Reflection API
- Java interop is the hardest issue
- Reflection literals
- Issues with generics
- Expression trees
- Compiler as a service

More Related Content

What's hot

Object-Oriented Programming with C#
Object-Oriented Programming with C#Object-Oriented Programming with C#
Object-Oriented Programming with C#
Svetlin Nakov
 
An Annotation Framework for Statically-Typed Syntax Trees
An Annotation Framework for Statically-Typed Syntax TreesAn Annotation Framework for Statically-Typed Syntax Trees
An Annotation Framework for Statically-Typed Syntax Trees
Ray Toal
 
Under the hood of scala implicits (kl10tch 10.03.2015)
Under the hood of scala implicits (kl10tch 10.03.2015)Under the hood of scala implicits (kl10tch 10.03.2015)
Under the hood of scala implicits (kl10tch 10.03.2015)
Alexander Podkhalyuzin
 
Types by Adform Research, Saulius Valatka
Types by Adform Research, Saulius ValatkaTypes by Adform Research, Saulius Valatka
Types by Adform Research, Saulius Valatka
Vasil Remeniuk
 
Sql basics joi ns and common commands (1)
Sql basics  joi ns and common commands (1)Sql basics  joi ns and common commands (1)
Sql basics joi ns and common commands (1)
johnnygoodman
 
2.1 Recap From Day One
2.1 Recap From Day One2.1 Recap From Day One
2.1 Recap From Day One
retronym
 

What's hot (20)

Object-Oriented Programming with C#
Object-Oriented Programming with C#Object-Oriented Programming with C#
Object-Oriented Programming with C#
 
Javaz. Functional design in Java 8.
Javaz. Functional design in Java 8.Javaz. Functional design in Java 8.
Javaz. Functional design in Java 8.
 
An Annotation Framework for Statically-Typed Syntax Trees
An Annotation Framework for Statically-Typed Syntax TreesAn Annotation Framework for Statically-Typed Syntax Trees
An Annotation Framework for Statically-Typed Syntax Trees
 
OCP Java SE 8 Exam - Sample Questions - Lambda Expressions
OCP Java SE 8 Exam - Sample Questions - Lambda Expressions OCP Java SE 8 Exam - Sample Questions - Lambda Expressions
OCP Java SE 8 Exam - Sample Questions - Lambda Expressions
 
Under the hood of scala implicits (kl10tch 10.03.2015)
Under the hood of scala implicits (kl10tch 10.03.2015)Under the hood of scala implicits (kl10tch 10.03.2015)
Under the hood of scala implicits (kl10tch 10.03.2015)
 
A Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOA Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIO
 
PROLOG: Fact Roles And Queries In Prolog
PROLOG: Fact Roles And Queries In PrologPROLOG: Fact Roles And Queries In Prolog
PROLOG: Fact Roles And Queries In Prolog
 
ALF 5 - Parser Top-Down (2018)
ALF 5 - Parser Top-Down (2018)ALF 5 - Parser Top-Down (2018)
ALF 5 - Parser Top-Down (2018)
 
ICLP-DC12
ICLP-DC12ICLP-DC12
ICLP-DC12
 
02 Java Language And OOP Part II LAB
02 Java Language And OOP Part II LAB02 Java Language And OOP Part II LAB
02 Java Language And OOP Part II LAB
 
Chaps 1-3-ai-prolog
Chaps 1-3-ai-prologChaps 1-3-ai-prolog
Chaps 1-3-ai-prolog
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
Tokyo F# meetup 14-08-03
Tokyo F# meetup 14-08-03Tokyo F# meetup 14-08-03
Tokyo F# meetup 14-08-03
 
Java session4
Java session4Java session4
Java session4
 
Types by Adform Research, Saulius Valatka
Types by Adform Research, Saulius ValatkaTypes by Adform Research, Saulius Valatka
Types by Adform Research, Saulius Valatka
 
Linq And Its Impact On The.Net Framework
Linq And Its Impact On The.Net FrameworkLinq And Its Impact On The.Net Framework
Linq And Its Impact On The.Net Framework
 
Sql basics joi ns and common commands (1)
Sql basics  joi ns and common commands (1)Sql basics  joi ns and common commands (1)
Sql basics joi ns and common commands (1)
 
Prolog
PrologProlog
Prolog
 
Under the hood of scala implicits (Scala eXchange 2014)
Under the hood of scala implicits (Scala eXchange 2014)Under the hood of scala implicits (Scala eXchange 2014)
Under the hood of scala implicits (Scala eXchange 2014)
 
2.1 Recap From Day One
2.1 Recap From Day One2.1 Recap From Day One
2.1 Recap From Day One
 

Viewers also liked (10)

Swift and Kotlin Presentation
Swift and Kotlin PresentationSwift and Kotlin Presentation
Swift and Kotlin Presentation
 
Flexible Types in Kotlin - JVMLS 2015
Flexible Types in Kotlin - JVMLS 2015Flexible Types in Kotlin - JVMLS 2015
Flexible Types in Kotlin - JVMLS 2015
 
Introduction to Kotlin: Brief and clear
Introduction to Kotlin: Brief and clearIntroduction to Kotlin: Brief and clear
Introduction to Kotlin: Brief and clear
 
Intro to kotlin
Intro to kotlinIntro to kotlin
Intro to kotlin
 
The Kotlin Programming Language
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Language
 
Functions and data
Functions and dataFunctions and data
Functions and data
 
JVMLS 2016. Coroutines in Kotlin
JVMLS 2016. Coroutines in KotlinJVMLS 2016. Coroutines in Kotlin
JVMLS 2016. Coroutines in Kotlin
 
Kotlin for Android: Brief and Clear
Kotlin for Android: Brief and ClearKotlin for Android: Brief and Clear
Kotlin for Android: Brief and Clear
 
Kotlin presentation
Kotlin presentation Kotlin presentation
Kotlin presentation
 
Kotlin: Challenges in JVM language design
Kotlin: Challenges in JVM language designKotlin: Challenges in JVM language design
Kotlin: Challenges in JVM language design
 

Similar to Kotlin gets Reflection

Types by Adform Research
Types by Adform ResearchTypes by Adform Research
Types by Adform Research
Vasil Remeniuk
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
Mario Fusco
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
John De Goes
 
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
PROIDEA
 
Profiling and optimization
Profiling and optimizationProfiling and optimization
Profiling and optimization
g3_nittala
 

Similar to Kotlin gets Reflection (20)

Functional programming in f sharp
Functional programming in f sharpFunctional programming in f sharp
Functional programming in f sharp
 
Practical Functional Programming Presentation by Bogdan Hodorog
Practical Functional Programming Presentation by Bogdan HodorogPractical Functional Programming Presentation by Bogdan Hodorog
Practical Functional Programming Presentation by Bogdan Hodorog
 
C# programming
C# programming C# programming
C# programming
 
Testing for share
Testing for share Testing for share
Testing for share
 
Types by Adform Research
Types by Adform ResearchTypes by Adform Research
Types by Adform Research
 
Metaprogramming in Scala 2.10, Eugene Burmako,
Metaprogramming  in Scala 2.10, Eugene Burmako, Metaprogramming  in Scala 2.10, Eugene Burmako,
Metaprogramming in Scala 2.10, Eugene Burmako,
 
python
pythonpython
python
 
The Ring programming language version 1.8 book - Part 37 of 202
The Ring programming language version 1.8 book - Part 37 of 202The Ring programming language version 1.8 book - Part 37 of 202
The Ring programming language version 1.8 book - Part 37 of 202
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
 
SOLID mit Java 8
SOLID mit Java 8SOLID mit Java 8
SOLID mit Java 8
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
 
All About ... Functions
All About ... FunctionsAll About ... Functions
All About ... Functions
 
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
 
Top Python Online Training Institutes in Bangalore
Top Python Online Training Institutes in BangaloreTop Python Online Training Institutes in Bangalore
Top Python Online Training Institutes in Bangalore
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
 
Profiling and optimization
Profiling and optimizationProfiling and optimization
Profiling and optimization
 
Scalaz 8: A Whole New Game
Scalaz 8: A Whole New GameScalaz 8: A Whole New Game
Scalaz 8: A Whole New Game
 
Introduction to Functional Languages
Introduction to Functional LanguagesIntroduction to Functional Languages
Introduction to Functional Languages
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Intro
 
Fp in scala part 1
Fp in scala part 1Fp in scala part 1
Fp in scala part 1
 

More from Andrey Breslav

Kotlin (Introduction for students)
Kotlin (Introduction for students)Kotlin (Introduction for students)
Kotlin (Introduction for students)
Andrey Breslav
 
Kotlin: Incompetence * Motivation = Innovation?
Kotlin: Incompetence * Motivation = Innovation?Kotlin: Incompetence * Motivation = Innovation?
Kotlin: Incompetence * Motivation = Innovation?
Andrey Breslav
 
Who's More Functional: Kotlin, Groovy, Scala, or Java?
Who's More Functional: Kotlin, Groovy, Scala, or Java?Who's More Functional: Kotlin, Groovy, Scala, or Java?
Who's More Functional: Kotlin, Groovy, Scala, or Java?
Andrey Breslav
 
JavaOne2012: Kotlin: Practical Aspects of JVM Language Implementation
JavaOne2012: Kotlin: Practical Aspects of JVM Language ImplementationJavaOne2012: Kotlin: Practical Aspects of JVM Language Implementation
JavaOne2012: Kotlin: Practical Aspects of JVM Language Implementation
Andrey Breslav
 
[JVMLS 12] Kotlin / Java Interop
[JVMLS 12] Kotlin / Java Interop[JVMLS 12] Kotlin / Java Interop
[JVMLS 12] Kotlin / Java Interop
Andrey Breslav
 
Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011
Andrey Breslav
 
Kotlin @ StrangeLoop 2011
Kotlin @ StrangeLoop 2011Kotlin @ StrangeLoop 2011
Kotlin @ StrangeLoop 2011
Andrey Breslav
 

More from Andrey Breslav (14)

2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
 
Shoulders of giants: Languages Kotlin learned from
Shoulders of giants: Languages Kotlin learned fromShoulders of giants: Languages Kotlin learned from
Shoulders of giants: Languages Kotlin learned from
 
Future of Kotlin - How agile can language development be?
Future of Kotlin - How agile can language development be?Future of Kotlin - How agile can language development be?
Future of Kotlin - How agile can language development be?
 
Eval4j @ JVMLS 2014
Eval4j @ JVMLS 2014Eval4j @ JVMLS 2014
Eval4j @ JVMLS 2014
 
Kotlin (Introduction for students)
Kotlin (Introduction for students)Kotlin (Introduction for students)
Kotlin (Introduction for students)
 
Language Design Trade-offs
Language Design Trade-offsLanguage Design Trade-offs
Language Design Trade-offs
 
Kotlin: Incompetence * Motivation = Innovation?
Kotlin: Incompetence * Motivation = Innovation?Kotlin: Incompetence * Motivation = Innovation?
Kotlin: Incompetence * Motivation = Innovation?
 
Who's More Functional: Kotlin, Groovy, Scala, or Java?
Who's More Functional: Kotlin, Groovy, Scala, or Java?Who's More Functional: Kotlin, Groovy, Scala, or Java?
Who's More Functional: Kotlin, Groovy, Scala, or Java?
 
JavaOne2012: Kotlin: Practical Aspects of JVM Language Implementation
JavaOne2012: Kotlin: Practical Aspects of JVM Language ImplementationJavaOne2012: Kotlin: Practical Aspects of JVM Language Implementation
JavaOne2012: Kotlin: Practical Aspects of JVM Language Implementation
 
[JVMLS 12] Kotlin / Java Interop
[JVMLS 12] Kotlin / Java Interop[JVMLS 12] Kotlin / Java Interop
[JVMLS 12] Kotlin / Java Interop
 
Kotlin @ Devoxx 2011
Kotlin @ Devoxx 2011Kotlin @ Devoxx 2011
Kotlin @ Devoxx 2011
 
Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011
 
Kotlin @ CSClub & Yandex
Kotlin @ CSClub & YandexKotlin @ CSClub & Yandex
Kotlin @ CSClub & Yandex
 
Kotlin @ StrangeLoop 2011
Kotlin @ StrangeLoop 2011Kotlin @ StrangeLoop 2011
Kotlin @ StrangeLoop 2011
 

Recently uploaded

Recently uploaded (20)

Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 

Kotlin gets Reflection