├── .gitignore
├── LICENSE.txt
├── README.md
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── instructor
├── advanced
│ └── org
│ │ └── jetbrains
│ │ └── kotlinworkshop
│ │ └── advanced
│ │ ├── _10Asynchronous
│ │ ├── 10_Timeout.kt
│ │ ├── 11_Sequential.kt
│ │ ├── 12_Concurrent.kt
│ │ ├── 13_Lazy.kt
│ │ ├── 14_Dispatchers.kt
│ │ ├── 15_Channels.kt
│ │ ├── 16_ClosingChannels.kt
│ │ ├── 17_ProduceConsume.kt
│ │ ├── 18_Pipeline.kt
│ │ ├── 19_SharedState.kt
│ │ ├── 1_LongRunningProcess.kt
│ │ ├── 20_Actors.kt
│ │ ├── 2_SuspendableComputation.kt
│ │ ├── 3_SuspendableComputationLoop.kt
│ │ ├── 4_SuspendableComputationSleep.kt
│ │ ├── 5_SuspendableComputationDelay.kt
│ │ ├── 6A_Comparison.kt
│ │ ├── 6_SuspendableComputationJoin.kt
│ │ ├── 7_WorkingWithJobs.kt
│ │ ├── 8_NonCancellable.kt
│ │ └── 9_Cancellable.kt
│ │ ├── _1Object
│ │ ├── _1Object.kt
│ │ ├── _2CompanionObject.kt
│ │ ├── _3JSingleton.java
│ │ ├── _4UsingCompanionObjectFromJava.java
│ │ └── _5UsingKotlinObjectFromJava.java
│ │ ├── _2Interop
│ │ ├── Session.java
│ │ ├── UsingEmployee.java
│ │ ├── UsingThrow.java
│ │ ├── _1PlatformTypes.kt
│ │ ├── _2ExtensionsFromJava.java
│ │ ├── _3InteropAnnotations.kt
│ │ └── _4Throws.kt
│ │ ├── _3InlineFunctions
│ │ ├── _1RunFunction.kt
│ │ ├── _2LetFunction.kt
│ │ ├── _3SynchronizedFunction.kt
│ │ ├── _4TakeIfAndTakeUnlessFunctions.kt
│ │ ├── _5RepeatFunction.kt
│ │ └── _6NoInline.kt
│ │ ├── _4Returns
│ │ ├── _1NonLocalReturns.kt
│ │ ├── _2LocalReturns.kt
│ │ └── _3Nothing.kt
│ │ ├── _5Reified
│ │ ├── _1TypeErasure.kt
│ │ ├── _2Reified.kt
│ │ ├── _3FilterIsInstance.kt
│ │ ├── _4ClassReferences.kt
│ │ ├── _5Validators.kt
│ │ └── _6RestrictionsOnReifiedTypeParameters.kt
│ │ ├── _6LazyEvaluation
│ │ ├── _1AsSequence.kt
│ │ └── _2GenerateSequence.kt
│ │ ├── _7FunctionalConstructs
│ │ ├── _1AlgebraicDataTypes.kt
│ │ ├── _2Currying.kt
│ │ ├── _3Partials.kt
│ │ ├── _4Composition.kt
│ │ ├── _5Functors.kt
│ │ ├── _6Applicatives.kt
│ │ └── _7Monads.kt
│ │ ├── _8Dsl
│ │ ├── _1ExtensionWithInfix.kt
│ │ ├── _2Invoke.kt
│ │ ├── _3LambdasWithReceivers.kt
│ │ ├── _4DslSample.kt
│ │ └── _5HtmlExample.kt
│ │ └── _9Metaprogramming
│ │ ├── _1Annotations.kt
│ │ ├── _2JavaReflection.kt
│ │ └── _3KotlinReflection.kt
├── introduction
│ ├── cmdline
│ │ ├── Hello.class
│ │ ├── Hello.java
│ │ ├── HelloKt.class
│ │ ├── Hellokt.jar
│ │ ├── META-INF
│ │ │ └── main.kotlin_module
│ │ └── hello.kt
│ └── org
│ │ └── jetbrains
│ │ └── kotlinworkshop
│ │ └── introduction
│ │ ├── _10Conventions
│ │ └── _1OperatorOverloading.kt
│ │ ├── _11Generics
│ │ ├── _1Basics.kt
│ │ ├── _2Invariance.kt
│ │ ├── _3Covariance.kt
│ │ └── _4Contravariance.kt
│ │ ├── _1Intro
│ │ ├── _0Main.kt
│ │ ├── _1Variables.kt
│ │ ├── _2Numbers.kt
│ │ ├── _3Functions.kt
│ │ ├── _4LocalFunctions.kt
│ │ ├── _5Constants.kt
│ │ ├── _6BasicInterop.kt
│ │ └── _7FromJava.java
│ │ ├── _2ControlStructures
│ │ ├── _1IfAndWhen.kt
│ │ ├── _2Loops.kt
│ │ ├── _3Iterating.kt
│ │ └── _4Ranges.kt
│ │ ├── _3Classes
│ │ ├── _10NestedClasses.kt
│ │ ├── _11TypeAliases.kt
│ │ ├── _1Classes.kt
│ │ ├── _2PrimaryConstructor.kt
│ │ ├── _3Constructors.kt
│ │ ├── _4Properties.kt
│ │ ├── _5MutableProperty.kt
│ │ ├── _6Equals.kt
│ │ ├── _7Tuples.kt
│ │ ├── _8DataClass.kt
│ │ ├── _9Destructuring.kt
│ │ └── javaCode
│ │ │ ├── Person.java
│ │ │ └── Rectangle.java
│ │ ├── _4Hierarchies
│ │ ├── _1Interfaces.kt
│ │ ├── _2AbstractClasses.kt
│ │ └── _3ClassInheritance.kt
│ │ ├── _5Nullability
│ │ ├── _1Nullability.kt
│ │ ├── _2Safecast.kt
│ │ └── _3LateInit.kt
│ │ ├── _6Extensions
│ │ └── _1Extensions.kt
│ │ ├── _7Lambdas
│ │ ├── _1HigherOrder.kt
│ │ ├── _2Lambdas.kt
│ │ ├── _3DestructuringInLambdas.kt
│ │ └── _4AnonymousFunctions.kt
│ │ ├── _8Delegation
│ │ ├── _1ClassDelegation.kt
│ │ ├── _2LazyProperty.kt
│ │ ├── _3Observable.kt
│ │ └── _4CustomDelegation.kt
│ │ ├── _9Functional
│ │ ├── _1ListOperators.kt
│ │ ├── _2Folds.kt
│ │ ├── _3RefactoringFunctional.kt
│ │ ├── _4RemovingState.kt
│ │ ├── _5TransformingData.kt
│ │ ├── _6VariousPatterns.kt
│ │ ├── _7TailRecursion.kt
│ │ └── _8Memoisation.kt
│ │ └── _Shared
│ │ ├── AlbumData.kt
│ │ ├── Customer.kt
│ │ ├── CustomerJava.java
│ │ └── CustomerRepository.kt
└── quizzes
│ └── org
│ └── jetbrains
│ └── kotlinworkshop
│ └── quizzes
│ ├── _1Intro
│ ├── _1IntroTasks.kt
│ └── _2Foo.kt
│ ├── _2Extensions
│ ├── Extensions.kt
│ ├── MemberVsExtension.kt
│ ├── ParentVsChild.kt
│ ├── ParentVsChildJava.java
│ ├── RepeatExample.kt
│ └── UsingRepeatFromJava.java
│ ├── _3Classes
│ ├── Evaluation.kt
│ ├── Foo.kt
│ ├── InnerAndNested.kt
│ ├── Person.kt
│ ├── UsePersonFromJava.java
│ └── Visibility.kt
│ ├── _4Nullability
│ ├── Lists.kt
│ ├── Name.kt
│ ├── SafeCasts.kt
│ └── isNullOrEmpty.kt
│ ├── _5TypeSystem
│ ├── JavaClass.java
│ ├── Parent.java
│ ├── Subclass.java
│ ├── Usage.java
│ ├── _1NPE.kt
│ ├── _2ExplicitTypeSpecification.kt
│ ├── _2NullInList.kt
│ └── _3NPEDuringInitialization.kt
│ ├── _6Lambdas
│ └── Heroes.kt
│ └── _7InlineAndLazyIteration
│ ├── Inline.kt
│ ├── IntermediateCollections.kt
│ └── LazyIteration.kt
├── jetbrainslogo.png
├── kotlinlogo.png
├── settings.gradle
└── student
├── tasks
└── org
│ └── jetbrains
│ └── kotlinworkshop
│ └── student
│ └── single
│ ├── _0Nullability
│ ├── MessageUtil.java
│ └── Task.kt
│ ├── _1BreakingSafety
│ ├── JavaClass.java
│ ├── _1NPE.kt
│ ├── _2NullInList.kt
│ ├── _3NotImmutableProperty.kt
│ └── _4NPEDuringInitialization.kt
│ ├── _2Shop
│ ├── JavaCode.java
│ ├── _10GroupBy.kt
│ ├── _11Partition.kt
│ ├── _12Fold.kt
│ ├── _13CompoundTasks.kt
│ ├── _14SmthWithCollections.kt
│ ├── _1Introduction.kt
│ ├── _2FilterMap.kt
│ ├── _3AllAnyAndOtherPredicates.kt
│ ├── _4FlatMap.kt
│ ├── _5MaxMin.kt
│ ├── _6Sort.kt
│ ├── _7Sum.kt
│ ├── _8Zip.kt
│ ├── _9AssociateBy.kt
│ └── shop.kt
│ ├── _3HtmlBuilders
│ ├── Task.kt
│ ├── data.kt
│ ├── html.kt
│ └── htmlDemo.kt
│ ├── _3TaxiPark
│ ├── TaxiPark.kt
│ ├── _1FakeDrivers.kt
│ ├── _2FaithfulPassengers.kt
│ ├── _3FrequentPassengers.kt
│ ├── _4SmartPassengers.kt
│ ├── _5FrequentTripDuration.kt
│ └── _6TestParetoPrinciple.kt
│ ├── _4Generics
│ └── GenericFunctions.kt
│ ├── _5LazyProperty
│ └── LazyProperty.kt
│ ├── _6WithApply
│ └── UsingWithApplyFunctions.kt
│ ├── _7CreatingDsl
│ ├── BreakfastMenu.kt
│ ├── BreakfastMenuBonusTask.kt
│ ├── breakfastMenu.xml
│ └── createBreakfastMenu.kt
│ └── _8Conventions
│ ├── MyDate.kt
│ ├── MyDateUsage.kt
│ └── MyDateUtil.kt
└── tests
└── org
└── jetbrains
└── kotlinworkshop
└── student
└── single
├── _0Nullability
└── TestSendMessage.kt
├── _1BreakingSafety
├── _1TestNPE.kt
├── _2TestNullInList.kt
├── _3TestNotImmutableProperty.kt
└── _4TestNPEDuringInitialization.kt
├── _2Shop
├── ShopBuilders.kt
├── TestShop.kt
├── _10GroupBy.kt
├── _11Partition.kt
├── _12Fold.kt
├── _13CompoundTasks.kt
├── _14SmthWithCollections.kt
├── _1Introduction.kt
├── _2FilterMap.kt
├── _3AllAnyAndOtherPredicates.kt
├── _4FlatMap.kt
├── _5MaxMin.kt
├── _6Sort.kt
├── _7Sum.kt
├── _8Zip.kt
└── _9AssociateBy.kt
├── _3HtmlBuilders
└── TestHtmlBuilders.kt
├── _3TaxiPark
├── TestTaxiParkUtil.kt
├── _1TestFakeDrivers.kt
├── _2TestFaithfulPassengers.kt
├── _3TestFrequentPassengers.kt
├── _4TestSmartPassengers.kt
├── _5FrequentTripDuration.kt
└── _6TestParetoPrinciple.kt
├── _4Generics
└── TestGenericFunction.kt
├── _5LazyProperty
└── TestLazyProperty.kt
├── _6WithApply
└── TestUsingWithApplyFunctions.kt
├── _7CreatingDsl
└── TestBreakfastMenuCreation.kt
└── _8Conventions
├── DateUtil.kt
├── TestTask1.kt
├── TestTask2.kt
├── TestTask3.kt
└── TestTask4And5.kt
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iws
2 | .ds_store
3 | out/
4 | .idea
5 | .idea_modules/
6 | .gradle/
7 | .idea/
8 | build/
9 | presources/
10 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Creative Commons Attribution-ShareAlike 4.0 International Public
2 | License
3 |
4 | By exercising the Licensed Rights (defined below), You accept and agree
5 | to be bound by the terms and conditions of this Creative Commons
6 | Attribution-ShareAlike 4.0 International Public License ("Public
7 | License"). To the extent this Public License may be interpreted as a
8 | contract, You are granted the Licensed Rights in consideration of Your
9 | acceptance of these terms and conditions, and the Licensor grants You
10 | such rights in consideration of benefits the Licensor receives from
11 | making the Licensed Material available under these terms and
12 | conditions.
13 |
14 |
15 | Section 1 -- Definitions.
16 |
17 | a. Adapted Material means material subject to Copyright and Similar
18 | Rights that is derived from or based upon the Licensed Material
19 | and in which the Licensed Material is translated, altered,
20 | arranged, transformed, or otherwise modified in a manner requiring
21 | permission under the Copyright and Similar Rights held by the
22 | Licensor. For purposes of this Public License, where the Licensed
23 | Material is a musical work, performance, or sound recording,
24 | Adapted Material is always produced where the Licensed Material is
25 | synched in timed relation with a moving image.
26 |
27 | b. Adapter's License means the license You apply to Your Copyright
28 | and Similar Rights in Your contributions to Adapted Material in
29 | accordance with the terms and conditions of this Public License.
30 |
31 | c. BY-SA Compatible License means a license listed at
32 | creativecommons.org/compatiblelicenses, approved by Creative
33 | Commons as essentially the equivalent of this Public License.
34 |
35 | d. Copyright and Similar Rights means copyright and/or similar rights
36 | closely related to copyright including, without limitation,
37 | performance, broadcast, sound recording, and Sui Generis Database
38 | Rights, without regard to how the rights are labeled or
39 | categorized. For purposes of this Public License, the rights
40 | specified in Section 2(b)(1)-(2) are not Copyright and Similar
41 | Rights.
42 |
43 | e. Effective Technological Measures means those measures that, in the
44 | absence of proper authority, may not be circumvented under laws
45 | fulfilling obligations under Article 11 of the WIPO Copyright
46 | Treaty adopted on December 20, 1996, and/or similar international
47 | agreements.
48 |
49 | f. Exceptions and Limitations means fair use, fair dealing, and/or
50 | any other exception or limitation to Copyright and Similar Rights
51 | that applies to Your use of the Licensed Material.
52 |
53 | g. License Elements means the license attributes listed in the name
54 | of a Creative Commons Public License. The License Elements of this
55 | Public License are Attribution and ShareAlike.
56 |
57 | h. Licensed Material means the artistic or literary work, database,
58 | or other material to which the Licensor applied this Public
59 | License.
60 |
61 | i. Licensed Rights means the rights granted to You subject to the
62 | terms and conditions of this Public License, which are limited to
63 | all Copyright and Similar Rights that apply to Your use of the
64 | Licensed Material and that the Licensor has authority to license.
65 |
66 | j. Licensor means the individual(s) or entity(ies) granting rights
67 | under this Public License.
68 |
69 | k. Share means to provide material to the public by any means or
70 | process that requires permission under the Licensed Rights, such
71 | as reproduction, public display, public performance, distribution,
72 | dissemination, communication, or importation, and to make material
73 | available to the public including in ways that members of the
74 | public may access the material from a place and at a time
75 | individually chosen by them.
76 |
77 | l. Sui Generis Database Rights means rights other than copyright
78 | resulting from Directive 96/9/EC of the European Parliament and of
79 | the Council of 11 March 1996 on the legal protection of databases,
80 | as amended and/or succeeded, as well as other essentially
81 | equivalent rights anywhere in the world.
82 |
83 | m. You means the individual or entity exercising the Licensed Rights
84 | under this Public License. Your has a corresponding meaning.
85 |
86 |
87 | Section 2 -- Scope.
88 |
89 | a. License grant.
90 |
91 | 1. Subject to the terms and conditions of this Public License,
92 | the Licensor hereby grants You a worldwide, royalty-free,
93 | non-sublicensable, non-exclusive, irrevocable license to
94 | exercise the Licensed Rights in the Licensed Material to:
95 |
96 | a. reproduce and Share the Licensed Material, in whole or
97 | in part; and
98 |
99 | b. produce, reproduce, and Share Adapted Material.
100 |
101 | 2. Exceptions and Limitations. For the avoidance of doubt, where
102 | Exceptions and Limitations apply to Your use, this Public
103 | License does not apply, and You do not need to comply with
104 | its terms and conditions.
105 |
106 | 3. Term. The term of this Public License is specified in Section
107 | 6(a).
108 |
109 | 4. Media and formats; technical modifications allowed. The
110 | Licensor authorizes You to exercise the Licensed Rights in
111 | all media and formats whether now known or hereafter created,
112 | and to make technical modifications necessary to do so. The
113 | Licensor waives and/or agrees not to assert any right or
114 | authority to forbid You from making technical modifications
115 | necessary to exercise the Licensed Rights, including
116 | technical modifications necessary to circumvent Effective
117 | Technological Measures. For purposes of this Public License,
118 | simply making modifications authorized by this Section 2(a)
119 | (4) never produces Adapted Material.
120 |
121 | 5. Downstream recipients.
122 |
123 | a. Offer from the Licensor -- Licensed Material. Every
124 | recipient of the Licensed Material automatically
125 | receives an offer from the Licensor to exercise the
126 | Licensed Rights under the terms and conditions of this
127 | Public License.
128 |
129 | b. Additional offer from the Licensor -- Adapted Material.
130 | Every recipient of Adapted Material from You
131 | automatically receives an offer from the Licensor to
132 | exercise the Licensed Rights in the Adapted Material
133 | under the conditions of the Adapter's License You apply.
134 |
135 | c. No downstream restrictions. You may not offer or impose
136 | any additional or different terms or conditions on, or
137 | apply any Effective Technological Measures to, the
138 | Licensed Material if doing so restricts exercise of the
139 | Licensed Rights by any recipient of the Licensed
140 | Material.
141 |
142 | 6. No endorsement. Nothing in this Public License constitutes or
143 | may be construed as permission to assert or imply that You
144 | are, or that Your use of the Licensed Material is, connected
145 | with, or sponsored, endorsed, or granted official status by,
146 | the Licensor or others designated to receive attribution as
147 | provided in Section 3(a)(1)(A)(i).
148 |
149 | b. Other rights.
150 |
151 | 1. Moral rights, such as the right of integrity, are not
152 | licensed under this Public License, nor are publicity,
153 | privacy, and/or other similar personality rights; however, to
154 | the extent possible, the Licensor waives and/or agrees not to
155 | assert any such rights held by the Licensor to the limited
156 | extent necessary to allow You to exercise the Licensed
157 | Rights, but not otherwise.
158 |
159 | 2. Patent and trademark rights are not licensed under this
160 | Public License.
161 |
162 | 3. To the extent possible, the Licensor waives any right to
163 | collect royalties from You for the exercise of the Licensed
164 | Rights, whether directly or through a collecting society
165 | under any voluntary or waivable statutory or compulsory
166 | licensing scheme. In all other cases the Licensor expressly
167 | reserves any right to collect such royalties.
168 |
169 |
170 | Section 3 -- License Conditions.
171 |
172 | Your exercise of the Licensed Rights is expressly made subject to the
173 | following conditions.
174 |
175 | a. Attribution.
176 |
177 | 1. If You Share the Licensed Material (including in modified
178 | form), You must:
179 |
180 | a. retain the following if it is supplied by the Licensor
181 | with the Licensed Material:
182 |
183 | i. identification of the creator(s) of the Licensed
184 | Material and any others designated to receive
185 | attribution, in any reasonable manner requested by
186 | the Licensor (including by pseudonym if
187 | designated);
188 |
189 | ii. a copyright notice;
190 |
191 | iii. a notice that refers to this Public License;
192 |
193 | iv. a notice that refers to the disclaimer of
194 | warranties;
195 |
196 | v. a URI or hyperlink to the Licensed Material to the
197 | extent reasonably practicable;
198 |
199 | b. indicate if You modified the Licensed Material and
200 | retain an indication of any previous modifications; and
201 |
202 | c. indicate the Licensed Material is licensed under this
203 | Public License, and include the text of, or the URI or
204 | hyperlink to, this Public License.
205 |
206 | 2. You may satisfy the conditions in Section 3(a)(1) in any
207 | reasonable manner based on the medium, means, and context in
208 | which You Share the Licensed Material. For example, it may be
209 | reasonable to satisfy the conditions by providing a URI or
210 | hyperlink to a resource that includes the required
211 | information.
212 |
213 | 3. If requested by the Licensor, You must remove any of the
214 | information required by Section 3(a)(1)(A) to the extent
215 | reasonably practicable.
216 |
217 | b. ShareAlike.
218 |
219 | In addition to the conditions in Section 3(a), if You Share
220 | Adapted Material You produce, the following conditions also apply.
221 |
222 | 1. The Adapter's License You apply must be a Creative Commons
223 | license with the same License Elements, this version or
224 | later, or a BY-SA Compatible License.
225 |
226 | 2. You must include the text of, or the URI or hyperlink to, the
227 | Adapter's License You apply. You may satisfy this condition
228 | in any reasonable manner based on the medium, means, and
229 | context in which You Share Adapted Material.
230 |
231 | 3. You may not offer or impose any additional or different terms
232 | or conditions on, or apply any Effective Technological
233 | Measures to, Adapted Material that restrict exercise of the
234 | rights granted under the Adapter's License You apply.
235 |
236 |
237 | Section 4 -- Sui Generis Database Rights.
238 |
239 | Where the Licensed Rights include Sui Generis Database Rights that
240 | apply to Your use of the Licensed Material:
241 |
242 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right
243 | to extract, reuse, reproduce, and Share all or a substantial
244 | portion of the contents of the database;
245 |
246 | b. if You include all or a substantial portion of the database
247 | contents in a database in which You have Sui Generis Database
248 | Rights, then the database in which You have Sui Generis Database
249 | Rights (but not its individual contents) is Adapted Material,
250 | including for purposes of Section 3(b); and
251 |
252 | c. You must comply with the conditions in Section 3(a) if You Share
253 | all or a substantial portion of the contents of the database.
254 |
255 | For the avoidance of doubt, this Section 4 supplements and does not
256 | replace Your obligations under this Public License where the Licensed
257 | Rights include other Copyright and Similar Rights.
258 |
259 |
260 | Section 5 -- Disclaimer of Warranties and Limitation of Liability.
261 |
262 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
263 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
264 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
265 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
266 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
267 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
268 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
269 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
270 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
271 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
272 |
273 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
274 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
275 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
276 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
277 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
278 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
279 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
280 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
281 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
282 |
283 | c. The disclaimer of warranties and limitation of liability provided
284 | above shall be interpreted in a manner that, to the extent
285 | possible, most closely approximates an absolute disclaimer and
286 | waiver of all liability.
287 |
288 |
289 | Section 6 -- Term and Termination.
290 |
291 | a. This Public License applies for the term of the Copyright and
292 | Similar Rights licensed here. However, if You fail to comply with
293 | this Public License, then Your rights under this Public License
294 | terminate automatically.
295 |
296 | b. Where Your right to use the Licensed Material has terminated under
297 | Section 6(a), it reinstates:
298 |
299 | 1. automatically as of the date the violation is cured, provided
300 | it is cured within 30 days of Your discovery of the
301 | violation; or
302 |
303 | 2. upon express reinstatement by the Licensor.
304 |
305 | For the avoidance of doubt, this Section 6(b) does not affect any
306 | right the Licensor may have to seek remedies for Your violations
307 | of this Public License.
308 |
309 | c. For the avoidance of doubt, the Licensor may also offer the
310 | Licensed Material under separate terms or conditions or stop
311 | distributing the Licensed Material at any time; however, doing so
312 | will not terminate this Public License.
313 |
314 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
315 | License.
316 |
317 |
318 | Section 7 -- Other Terms and Conditions.
319 |
320 | a. The Licensor shall not be bound by any additional or different
321 | terms or conditions communicated by You unless expressly agreed.
322 |
323 | b. Any arrangements, understandings, or agreements regarding the
324 | Licensed Material not stated herein are separate from and
325 | independent of the terms and conditions of this Public License.
326 |
327 |
328 | Section 8 -- Interpretation.
329 |
330 | a. For the avoidance of doubt, this Public License does not, and
331 | shall not be interpreted to, reduce, limit, restrict, or impose
332 | conditions on any use of the Licensed Material that could lawfully
333 | be made without permission under this Public License.
334 |
335 | b. To the extent possible, if any provision of this Public License is
336 | deemed unenforceable, it shall be automatically reformed to the
337 | minimum extent necessary to make it enforceable. If the provision
338 | cannot be reformed, it shall be severed from this Public License
339 | without affecting the enforceability of the remaining terms and
340 | conditions.
341 |
342 | c. No term or condition of this Public License will be waived and no
343 | failure to comply consented to unless expressly agreed to by the
344 | Licensor.
345 |
346 | d. Nothing in this Public License constitutes or may be interpreted
347 | as a limitation upon, or waiver of, any privileges and immunities
348 | that apply to the Licensor or You, including from the legal
349 | processes of any jurisdiction or authority.
350 |
351 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
2 |
3 | ## Kotlin Workshop
4 |
5 | 
6 |
7 | A Kotlin workshop intended to be taught in two days.
8 |
9 | ### Structure
10 |
11 | This workshop is divided into two parts
12 |
13 | * Introduction to Kotlin
14 | * Advanced Kotlin
15 |
16 | It consists of
17 |
18 | * **Instructor Project**: Used to explain concepts, with existing code samples
19 | * **Student Project**: For students to complete
20 | * **Presentations**: For the instructor to use
21 | * **Questions**: For students to complete
22 |
23 | Both the Instructor Project and the slides have Introduction and Advanced modules included. While the Introduction
24 | has a lot of pre-built examples, it also serves as a canvas to show more code while teaching. However, please make sure that if you're
25 | a contributing author to this project, that you *do not* check-in any ad-hoc code. It's also recommended to use Scratch files in IntelliJ IDEA
26 | for this purpose.
27 |
28 | #### Presentations
29 |
30 | Slides for the workshop lead by Hadi Hariri can be found [here](https://docs.google.com/presentation/d/1zYWyDedyf0YhnLFF3TVpUqU3C8PKTuvR5P06L99MRn8/edit?usp=sharing).
31 |
32 | Presentations used for the workshop at KotlinConf:
33 | 1. [Intro](https://speakerdeck.com/svtk/1-intro-kotlin-workshop)
34 | 2. [Nullable Types](https://speakerdeck.com/svtk/2-nullable-types-in-kotlin-kotlin-workshop)
35 | 3. [Object-Oriented Programming in Kotlin](https://speakerdeck.com/svtk/3-object-oriented-programming-in-kotlin-kotlin-workshop)
36 | 4. [Kotlin Types](https://speakerdeck.com/svtk/4-kotlin-types-kotlin-workshop)
37 | 5. [Functional Programming in Kotlin](https://speakerdeck.com/svtk/5-functional-programming-kotlin-workshop)
38 | 6. [The Power of inline](https://speakerdeck.com/svtk/6-the-power-of-inline-kotlin-workshop)
39 | 7. [Lambda With Receiver](https://speakerdeck.com/svtk/7-lambda-with-receiver-kotlin-workshop)
40 | 8. [Conventions](https://speakerdeck.com/svtk/8-conventions-kotlin-workshop)
41 | 9. [Intro to Coroutines](https://speakerdeck.com/svtk/9-introduction-to-coroutines-kotlin-workshop)
42 |
43 | #### Questions
44 |
45 | Questions can be found [here](https://drive.google.com/file/d/18AiXqEzdJmNonc6Lo6eumeFmcVvC_9vk/view?usp=sharing). The keys to the questions are in the module `instructor/quizzes`.
46 |
47 | Note that the similar material can be found explained in detail in the following [Coursera course](https://www.coursera.org/learn/kotlin-for-java-developers).
48 |
49 | ### Authors
50 |
51 | This workshop includes material from the following authors:
52 |
53 | * [Hadi Hariri](https://github.com/hhariri)
54 | * [Svetlana Isakova](https://github.com/svtk)
55 | * [Dmitry Jemerov](https://github.com/yole)
56 | * [Roman Elizarov](https://github.com/elizarov)
57 |
58 | ### License and Usage
59 |
60 | The material provided in this repository, including but not limited to source code, presentations, notes and exercises is Copyright (c) 2017 JetBrains, and is provided as-is.
61 |
62 | 
63 |
64 | 
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
65 |
66 |
67 | JetBrains and Kotlin are Registered Trademarks of their respective trademark holders.
68 |
69 | #### Contributions
70 |
71 | We welcome all contributions to this workshop. If you feel you'd like to contribute something, create a fork and make a pull request. Bug fixes, comments, suggestions, all welcome.
72 |
73 | If you're contributing code or samples, please send a pull request. If you'd like to update the slides or questions, please contact [Hadi Hariri](https://github.com/hhariri).
74 |
75 | #### Usage and endorsements
76 |
77 | You are welcome to use the material in this workshop provided you abide by the corresponding license agreement. Additionally
78 |
79 | * By using this material, with or without any modification, JetBrains does not endorse any workshop or training that you may offer.
80 | * By using this material, with or without any modification, you may not use JetBrain's name to promote your workshop or training without prior written consent.
81 | * By using this material, provided there are no modifications, you may indicate that you are using JetBrains Kotlin Workshop Material.
82 |
83 | If you're interested in becoming an official JetBrains Training Partner, please [contact us](https://www.jetbrains.com/company/partners/become_a_partner.html)
84 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java'
3 | id 'org.jetbrains.kotlin.jvm' version '1.3.21'
4 | }
5 |
6 | group 'org.jetbrains.kotlin-workshop'
7 | version '1.0-SNAPSHOT'
8 |
9 | sourceCompatibility = 1.8
10 |
11 | repositories {
12 | mavenCentral()
13 | }
14 |
15 | dependencies {
16 | compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
17 | compile "org.jetbrains.kotlin:kotlin-reflect"
18 | compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1'
19 |
20 | testCompile 'org.junit.jupiter:junit-jupiter-engine:5.4.0'
21 | testCompile "org.jetbrains.kotlin:kotlin-test-junit5"
22 | }
23 |
24 | compileKotlin {
25 | kotlinOptions.jvmTarget = "1.8"
26 | }
27 | compileTestKotlin {
28 | kotlinOptions.jvmTarget = "1.8"
29 | }
30 | sourceSets {
31 | main.kotlin.srcDirs += 'instructor/introduction'
32 | main.kotlin.srcDirs += 'instructor/advanced'
33 | main.kotlin.srcDirs += 'instructor/quizzes'
34 | main.kotlin.srcDirs += 'student/tasks'
35 | test.kotlin.srcDirs += 'student/tests'
36 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kotlin/workshop/37552440e6e6a1f7607ea5722eef1e8d5578d4f5/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/10_Timeout.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.delay
4 | import kotlinx.coroutines.runBlocking
5 | import kotlinx.coroutines.withTimeout
6 |
7 |
8 | fun main() = runBlocking {
9 | withTimeout(3000) {
10 | timeoutProcess()
11 | }
12 | }
13 |
14 | suspend fun timeoutProcess() {
15 | delay(5000)
16 | println("timeoutProcess called")
17 | }
18 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/11_Sequential.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.delay
4 | import kotlinx.coroutines.runBlocking
5 | import kotlin.system.measureTimeMillis
6 |
7 |
8 | fun main() = runBlocking {
9 |
10 | val time = measureTimeMillis {
11 | val one = function1()
12 | val two = function2()
13 | println("Result is ${one + two}")
14 | }
15 | println("Total time: $time")
16 |
17 | }
18 |
19 |
20 | suspend fun function1(): Int {
21 | delay(1000)
22 | return 15
23 | }
24 |
25 | suspend fun function2(): Int {
26 | delay(1000)
27 | return 27
28 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/12_Concurrent.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.Dispatchers
4 | import kotlinx.coroutines.async
5 | import kotlinx.coroutines.runBlocking
6 | import kotlin.system.measureTimeMillis
7 |
8 |
9 | fun main() = runBlocking {
10 |
11 | val time = measureTimeMillis {
12 | val one = async(Dispatchers.Default) { function1() }
13 | val two = async(Dispatchers.Default) { function2() }
14 | println("Result is ${one.await() + two.await()}")
15 | }
16 | println("Total time: $time")
17 |
18 | }
19 |
20 |
21 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/13_Lazy.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.CoroutineStart
4 | import kotlinx.coroutines.Dispatchers
5 | import kotlinx.coroutines.async
6 | import kotlinx.coroutines.runBlocking
7 | import kotlin.system.measureTimeMillis
8 |
9 |
10 | fun main() = runBlocking {
11 |
12 | val time = measureTimeMillis {
13 | val one = async(Dispatchers.Default, CoroutineStart.LAZY) { function1() }
14 | val two = async(Dispatchers.Default, CoroutineStart.LAZY) { function2() }
15 | println("Result is ${one.await() + two.await()}")
16 | }
17 | println("Total time: $time")
18 |
19 | }
20 |
21 |
22 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/14_Dispatchers.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.*
4 |
5 |
6 | fun main() = runBlocking {
7 |
8 | val jobs = arrayListOf()
9 |
10 | jobs += launch(Dispatchers.Unconfined) {
11 | println("Unconfined: ${threadName()}")
12 | }
13 |
14 | jobs += launch() {
15 | isActive
16 | println("CommonPool: ${threadName()}")
17 | }
18 |
19 | jobs += launch(newSingleThreadContext("CustomThread")) {
20 | println("CustomThread: ${threadName()}")
21 | }
22 |
23 | /*jobs += launch(coroutineContext) {
24 | println("CustomThread: ${threadName()}")
25 | }*/
26 |
27 | }
28 |
29 |
30 |
31 |
32 | fun threadName(): String = Thread.currentThread().name
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/15_Channels.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.channels.Channel
4 | import kotlinx.coroutines.launch
5 | import kotlinx.coroutines.runBlocking
6 |
7 |
8 | fun main() = runBlocking {
9 | val channel = Channel()
10 |
11 | launch {
12 | for (x in 1..5) {
13 | channel.send(x * x)
14 | }
15 | }
16 | repeat(5) {
17 | println(channel.receive())
18 | }
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/16_ClosingChannels.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.channels.Channel
4 | import kotlinx.coroutines.launch
5 | import kotlinx.coroutines.runBlocking
6 |
7 |
8 | fun main() = runBlocking {
9 | val channel = Channel()
10 |
11 | launch {
12 | for (x in 1..7) {
13 | channel.send(x * x)
14 | }
15 | channel.close()
16 | }
17 | for (y in channel) {
18 | println(channel.receive())
19 | }
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/17_ProduceConsume.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.CoroutineScope
4 | import kotlinx.coroutines.channels.consumeEach
5 | import kotlinx.coroutines.channels.produce
6 | import kotlinx.coroutines.runBlocking
7 |
8 |
9 | fun main() = runBlocking {
10 | val squares = produceSquares()
11 | squares.consumeEach {
12 | println(it)
13 | }
14 | }
15 |
16 |
17 | fun CoroutineScope.produceSquares() = produce {
18 | for (x in 1..5) {
19 | send (x * x)
20 | }
21 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/18_Pipeline.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._18_Pipeline
2 |
3 | import kotlinx.coroutines.CoroutineScope
4 | import kotlinx.coroutines.channels.ReceiveChannel
5 | import kotlinx.coroutines.channels.produce
6 | import kotlinx.coroutines.runBlocking
7 |
8 |
9 | fun CoroutineScope.producerPipeline() = produce {
10 | var x = 1
11 | while (true) send(x++)
12 | }
13 |
14 | fun CoroutineScope.consumerPipeline(numbers: ReceiveChannel) = produce {
15 | for (x in numbers) {
16 | send(x * x)
17 | }
18 | }
19 |
20 | fun main() = runBlocking {
21 | val numbers = producerPipeline()
22 | val squares = consumerPipeline(numbers)
23 | for (i in 1..5) {
24 | println(squares.receive())
25 | }
26 | squares.cancel()
27 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/19_SharedState.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 |
4 | import kotlinx.coroutines.*
5 | import java.util.concurrent.Executors
6 | import kotlin.coroutines.CoroutineContext
7 | import kotlin.system.measureTimeMillis
8 |
9 |
10 | val counterContext = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
11 |
12 | var counter = 0
13 |
14 | fun main() = runBlocking {
15 | // Switch to counterContext for faster execution
16 | massiveRun(Dispatchers.Default) {
17 | withContext(counterContext) { // remove run when switching to counterContext
18 | counter++
19 | }
20 | }
21 | println("Counter = ${counter}")
22 | }
23 |
24 | suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
25 | val n = 1000
26 | val k = 1000
27 | val time = measureTimeMillis {
28 | val jobs = List(n) {
29 | GlobalScope.launch(context) {
30 | repeat(k) { action() }
31 | }
32 | }
33 | jobs.forEach { it.join() }
34 | }
35 | println("Completed ${ n * k} actions in $time ms")
36 |
37 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/1_LongRunningProcess.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 |
4 | fun main() {
5 |
6 |
7 | println("Starting here")
8 | longRunningProcess()
9 | println("Ending here")
10 |
11 | }
12 |
13 | fun longRunningProcess() {
14 | Thread.sleep(5000)
15 | println("in process")
16 | }
17 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/20_Actors.kt:
--------------------------------------------------------------------------------
1 | package com.hadihariri.kotlin.async
2 |
3 |
4 | import kotlinx.coroutines.CompletableDeferred
5 | import kotlinx.coroutines.CoroutineScope
6 | import kotlinx.coroutines.Dispatchers
7 | import kotlinx.coroutines.channels.actor
8 | import kotlinx.coroutines.runBlocking
9 | import org.jetbrains.kotlinworkshop.advanced._10Asynchronous.massiveRun
10 |
11 |
12 | sealed class CounterMessage
13 | object IncCounter: CounterMessage()
14 | class GetCounter(val response: CompletableDeferred): CounterMessage()
15 |
16 | fun CoroutineScope.counterActor() = actor {
17 | var counter = 0
18 | for (msg in channel) {
19 | when (msg) {
20 | is IncCounter -> counter++
21 | is GetCounter -> msg.response.complete(counter)
22 | }
23 | }
24 | }
25 |
26 | fun main() = runBlocking {
27 | val counter = counterActor()
28 | massiveRun(Dispatchers.Default) {
29 | counter.send(IncCounter)
30 | }
31 | val response = CompletableDeferred()
32 | counter.send(GetCounter(response))
33 | println("Counter = ${response.await()}")
34 | counter.close()
35 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/2_SuspendableComputation.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.launch
4 | import kotlinx.coroutines.runBlocking
5 |
6 | fun main() = runBlocking {
7 |
8 |
9 | println("Starting here")
10 | launch {
11 | suspendableProcess()
12 | }
13 | println("Ending here")
14 |
15 | }
16 |
17 | suspend fun suspendableProcess() {
18 | Thread.sleep(2000)
19 | println("in process")
20 | }
21 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/3_SuspendableComputationLoop.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.launch
4 | import kotlinx.coroutines.runBlocking
5 |
6 |
7 | fun main() = runBlocking {
8 |
9 |
10 | println("Starting here")
11 | launch {
12 |
13 | suspendableProcess()
14 | }
15 | println("Ending here")
16 | while (true) {}
17 | }
18 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/4_SuspendableComputationSleep.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.launch
4 | import kotlinx.coroutines.runBlocking
5 |
6 | fun main() = runBlocking {
7 | println("Starting here")
8 | launch() {
9 | suspendableProcess()
10 | }
11 | println("Ending here")
12 | Thread.sleep(4000)
13 | }
14 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/5_SuspendableComputationDelay.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.delay
4 | import kotlinx.coroutines.launch
5 | import kotlinx.coroutines.runBlocking
6 |
7 |
8 | fun main() = runBlocking {
9 | println("Starting here")
10 | launch {
11 | suspendableProcess()
12 | }
13 | println("Ending here")
14 | delay(4000)
15 | }
16 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/6A_Comparison.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.GlobalScope
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.launch
6 | import kotlinx.coroutines.runBlocking
7 | import kotlin.concurrent.thread
8 |
9 |
10 | fun threads() {
11 | val jobs = 1..100000
12 | jobs.forEach {
13 |
14 | thread {
15 | Thread.sleep(1000L)
16 | print(".")
17 | }
18 | }
19 | }
20 |
21 |
22 | fun coroutines() = runBlocking {
23 | val jobs = List(100000) {
24 | GlobalScope.launch() {
25 | delay(1000L)
26 | print(".")
27 | }
28 | }
29 | jobs.forEach { it.join() }
30 | }
31 |
32 |
33 |
34 | fun main() {
35 |
36 | coroutines()
37 | // threads()
38 |
39 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/6_SuspendableComputationJoin.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.launch
4 | import kotlinx.coroutines.runBlocking
5 |
6 | fun main() = runBlocking {
7 | println("Starting here")
8 | val job = launch() {
9 | suspendableProcess()
10 | }
11 | println("Ending here")
12 | job.join()
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/7_WorkingWithJobs.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.delay
4 | import kotlinx.coroutines.launch
5 | import kotlinx.coroutines.runBlocking
6 |
7 |
8 | fun main() = runBlocking {
9 | val job = launch {
10 | longRunning()
11 | }
12 | delay(4000)
13 | job.cancel()
14 | }
15 |
16 | suspend fun longRunning() {
17 | delay(10000)
18 | println("longRunning called")
19 | }
20 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/8_NonCancellable.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.delay
4 | import kotlinx.coroutines.launch
5 | import kotlinx.coroutines.runBlocking
6 |
7 |
8 | fun main() = runBlocking {
9 | val job = launch {
10 | var nextPrintTime = System.currentTimeMillis()
11 | var i = 0
12 | while (true) { // computation loop
13 | val currentTime = System.currentTimeMillis()
14 | if (currentTime >= nextPrintTime) {
15 | println("I'm sleeping ${i++} ...")
16 | nextPrintTime += 500L
17 | }
18 | } }
19 | delay(1300L) // delay a bit
20 | println("main: I'm tired of waiting!")
21 | job.cancel() // cancels the job
22 | delay(1300L) // delay a bit to see if it was cancelled....
23 | println("main: Now I can quit.")
24 | }
25 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/9_Cancellable.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous
2 |
3 | import kotlinx.coroutines.delay
4 | import kotlinx.coroutines.isActive
5 | import kotlinx.coroutines.launch
6 | import kotlinx.coroutines.runBlocking
7 |
8 |
9 | fun main() = runBlocking {
10 | val job = launch {
11 | var nextPrintTime = System.currentTimeMillis()
12 | var i = 0
13 | while (isActive) { // computation loop
14 | val currentTime = System.currentTimeMillis()
15 | if (currentTime >= nextPrintTime) {
16 | println("I'm sleeping ${i++} ...")
17 | nextPrintTime += 500L
18 | }
19 | } }
20 | delay(1300L) // delay a bit
21 | println("main: I'm tired of waiting!")
22 | job.cancel() // cancels the job
23 | delay(1300L) // delay a bit to see if it was cancelled....
24 | println("main: Now I can quit.")
25 | }
26 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_1Object/_1Object.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._1Object
2 |
3 | object KSingleton {
4 | fun foo() {}
5 | }
6 |
7 | fun main() {
8 | KSingleton.foo()
9 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_1Object/_2CompanionObject.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._1Object
2 |
3 | interface Factory {
4 | fun create(): T
5 | }
6 |
7 | // Companion object can implement an interface
8 | class A {
9 | private constructor()
10 |
11 | companion object : Factory {
12 | override fun create(): A {
13 | return A()
14 | }
15 |
16 | // to make it static use annotation
17 | @JvmStatic
18 | fun staticFunction() {
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_1Object/_3JSingleton.java:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._1Object;
2 |
3 | public class _3JSingleton {
4 | public final static _3JSingleton INSTANCE = new _3JSingleton();
5 |
6 | private _3JSingleton() {
7 | }
8 |
9 | public void foo() {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_1Object/_4UsingCompanionObjectFromJava.java:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._1Object;
2 |
3 | public class _4UsingCompanionObjectFromJava {
4 |
5 | public static void main(String[] args) {
6 |
7 | A.Companion.create();
8 | // A.create() //- doesn't compile
9 |
10 | A.Companion.staticFunction();
11 | A.staticFunction();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_1Object/_5UsingKotlinObjectFromJava.java:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._1Object;
2 |
3 | public class _5UsingKotlinObjectFromJava {
4 | public static void main(String[] args) {
5 | _3JSingleton.INSTANCE.foo();
6 | KSingleton.INSTANCE.foo();
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/Session.java:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._2Interop;
2 |
3 | public class Session {
4 | public String getDescription() {
5 | return null;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/UsingEmployee.java:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._2Interop;
2 |
3 | public class UsingEmployee {
4 |
5 | public static void main(String[] args) {
6 |
7 | Employee employee = new Employee();
8 |
9 | employee.getField();
10 | employee.setField("Value");
11 |
12 |
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/UsingThrow.java:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._2Interop;
2 |
3 | public class UsingThrow {
4 |
5 |
6 | public void usingThrow() {
7 | _4ThrowsKt.throwsException("Something");
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/_1PlatformTypes.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._2Interop
2 |
3 | fun main() {
4 | explicitNullableType()
5 | explicitNotNullType()
6 | noExplicitType()
7 | }
8 |
9 | fun noExplicitType() {
10 | val session = Session()
11 | val description = session.description
12 | println(description.length) // NPE
13 | }
14 |
15 | fun explicitNotNullType() {
16 | val session = Session()
17 | val description: String = session.description // IllegalStateException
18 | println(description.length)
19 |
20 | }
21 |
22 | fun explicitNullableType() {
23 | val session = Session()
24 | val description: String? = session.description // ok
25 | println(description?.length) // null
26 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/_2ExtensionsFromJava.java:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._2Interop;
2 |
3 |
4 | import static org.jetbrains.kotlinworkshop.advanced._8Dsl._1ExtensionWithInfixKt.toTitleCase;
5 |
6 | public class _2ExtensionsFromJava {
7 | public static void main(String[] args) {
8 | String sample = "to title case";
9 |
10 | toTitleCase("sample");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/_3InteropAnnotations.kt:
--------------------------------------------------------------------------------
1 | @file:JvmName("Foo")
2 |
3 | package org.jetbrains.kotlinworkshop.advanced._2Interop
4 |
5 |
6 | class Employee {
7 | // @JvmField will make this a field and eliminate property accessors
8 | var field = ""
9 | }
10 |
11 | fun process(input: List) {
12 |
13 | }
14 |
15 | @JvmName("processStrings")
16 | fun process(input: List) {
17 |
18 | }
19 |
20 |
21 | // Others: @JvmStatic, @JvmOverload, etc. See https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/index.html
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/_4Throws.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._2Interop
2 |
3 | import java.io.*
4 |
5 | //@Throws(IOException::class)
6 | fun throwsException(value: String) {
7 | throw IOException("Java needs to know this")
8 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_3InlineFunctions/_1RunFunction.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._3InlineFunctions
2 |
3 | val foo = run {
4 | println("Calculating foo...")
5 | "foo"
6 | }
7 |
8 | fun main() {
9 | println(foo)
10 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_3InlineFunctions/_2LetFunction.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._3InlineFunctions
2 |
3 | fun sendEmailTo(email: String) {
4 | /*...*/
5 | }
6 |
7 | fun example(email: String?) {
8 |
9 | if (email != null) sendEmailTo(email)
10 | email?.let { e -> sendEmailTo(e) }
11 |
12 | val e = getEmail()
13 | if (e != null) sendEmailTo(e)
14 |
15 | getEmail()?.let { sendEmailTo(it) }
16 | }
17 |
18 | inline fun T.let(block: (T) -> R): R = block(this)
19 |
20 | fun getEmail(): String? = null
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_3InlineFunctions/_3SynchronizedFunction.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._3InlineFunctions
2 |
3 | import java.util.concurrent.locks.*
4 | import kotlin.concurrent.*
5 |
6 | inline fun synchronized(lock: Lock, action: () -> T): T {
7 | lock.lock()
8 | try {
9 | return action()
10 | } finally {
11 | lock.unlock()
12 | }
13 | }
14 |
15 | fun main() {
16 |
17 | val l = ReentrantLock()
18 |
19 | synchronized(l) {
20 | // ...
21 | }
22 |
23 | l.withLock {
24 | // ...
25 | }
26 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_3InlineFunctions/_4TakeIfAndTakeUnlessFunctions.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._3InlineFunctions
2 |
3 | data class Contract(val info: String, val isSigned: Boolean)
4 |
5 | fun main() {
6 | val contract1 = Contract("Kotlin training", true)
7 | println(contract1.takeIf { it.isSigned }) // contract1
8 |
9 | val contract2 = Contract("Other training", false)
10 | println(contract2.takeIf { it.isSigned }) // null
11 |
12 | val number = 42
13 | println(number.takeIf { it > 10 }) // 42
14 |
15 | val other = 2
16 | println(other.takeIf { it > 10 }) // null
17 |
18 | println(contract1.takeUnless { it.isSigned }) // null
19 |
20 | println(contract2.takeUnless { it.isSigned }) // contract2
21 |
22 | println(number.takeUnless { it > 10 }) // null
23 |
24 | println(other.takeUnless { it > 10 }) // 2
25 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_3InlineFunctions/_5RepeatFunction.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._3InlineFunctions
2 |
3 | fun main() {
4 | repeat(10) {
5 | println("Welcome!")
6 | }
7 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_3InlineFunctions/_6NoInline.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._3InlineFunctions
2 |
3 |
4 | // adding inline below changes things
5 | // add params noinline
6 | inline fun operation(x: Int, y: Int, noinline func: (Int, Int) -> Int) {
7 | println("Function being called")
8 | func(x, y)
9 | println("Function was called")
10 |
11 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_4Returns/_1NonLocalReturns.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._4Returns
2 |
3 |
4 | fun main() {
5 | containingFunction()
6 |
7 | }
8 |
9 | // non-local returns
10 | fun containingFunction() {
11 | val numbers = 1..100
12 | numbers.forEach {
13 | if (it % 5 == 0) return
14 | }
15 | println("Hello")
16 | }
17 |
18 | inline fun Iterable.myForEach(f: (T) -> Unit) {
19 | for (element in this) f(element)
20 | }
21 |
22 | fun containingFunction2() {
23 | val numbers = 1..100
24 | numbers.myForEach {
25 | if (it % 5 == 0) return
26 | }
27 | println("Hello")
28 | }
29 |
30 |
31 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_4Returns/_2LocalReturns.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._4Returns
2 |
3 | fun main() {
4 |
5 | }
6 |
7 | fun containingFunction3() {
8 | val numbers = 1..100
9 | numbers.forEach {
10 | if (it % 5 == 0) return@forEach
11 | }
12 | println("Hello")
13 | }
14 |
15 | fun containingFunction4() {
16 | val numbers = 1..100
17 | numbers.forEach myLabel@ {
18 | if (it % 5 == 0) return@myLabel
19 | }
20 | }
21 |
22 | fun containingFunction5() {
23 | val numbers = 1..100
24 | numbers.forEach(fun(element) {
25 | if (element % 5 == 0) return
26 | })
27 | println("Hello")
28 | }
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_4Returns/_3Nothing.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._4Returns
2 |
3 | // Add Nothing
4 | fun endlessLoop() {
5 |
6 | while (true) {
7 | // do something
8 | }
9 |
10 | }
11 |
12 |
13 | fun main() {
14 |
15 |
16 | endlessLoop()
17 | println("Never will reach here")
18 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_5Reified/_1TypeErasure.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._5Reified
2 |
3 | // Erasure of Generic Types
4 |
5 | // Erasure of Generic Methods
6 |
7 | class Node(val data: T, val next: Node)
8 |
9 | /*
10 | public final class Node {
11 |
12 | private final Ljava/lang/Object; data
13 |
14 | public final getData()Ljava/lang/Object;
15 |
16 | private final LNode; next
17 |
18 | public final getNext()LNode;
19 |
20 | public (Ljava/lang/Object;LNode;)V
21 | }
22 |
23 | */
24 |
25 | fun foo(t: T) {}
26 | fun > bar(t: T) {}
27 |
28 | /*
29 | public final static foo(Ljava/lang/Object;)V
30 |
31 | public final static bar(Ljava/lang/Comparable;)V
32 | */
33 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_5Reified/_2Reified.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._5Reified
2 |
3 | inline fun isA(value: Any) = value is T
4 |
5 | fun main() {
6 | println(isA("abc"))
7 | println(isA(123))
8 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_5Reified/_3FilterIsInstance.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._5Reified
2 |
3 | fun main() {
4 | val anys: List =
5 | listOf(1, "one", 2.0)
6 |
7 | val strings: List =
8 | anys.
9 | filterIsInstance()
10 | /*
11 | The code generated by the compiler
12 | instead of calling inline function 'filterIsInstance':
13 |
14 | val destination = mutableListOf()
15 | for (element in this) {
16 | if (element is String) {
17 | destination.add(element)
18 | }
19 | }
20 | val strings = destination
21 | */
22 |
23 | println(strings)
24 | }
25 |
26 | inline fun
27 | Iterable<*>.filterIsInstance(): List {
28 |
29 | val destination = mutableListOf()
30 | for (element in this) {
31 | if (element is T) {
32 | destination.add(element)
33 | }
34 | }
35 | return destination
36 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_5Reified/_4ClassReferences.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._5Reified
2 |
3 | import java.util.*
4 |
5 | class Service
6 |
7 | fun main() {
8 |
9 | ServiceLoader.load(Service::class.java)
10 |
11 | loadService()
12 | }
13 |
14 | inline fun loadService() =
15 | ServiceLoader.load(T::class.java)
16 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_5Reified/_5Validators.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._5Reified
2 |
3 | import kotlin.reflect.*
4 |
5 | interface FieldValidator {
6 | fun validate(input: T): Boolean
7 | }
8 |
9 | object Validators {
10 | private val validators = mutableMapOf, FieldValidator<*>>()
11 |
12 | fun registerValidator(
13 | kClass: KClass, fieldValidator: FieldValidator) {
14 | validators[kClass] = fieldValidator
15 | }
16 |
17 | @Suppress("UNCHECKED_CAST")
18 | operator fun get(kClass: KClass): FieldValidator? =
19 | validators[kClass] as FieldValidator?
20 | }
21 |
22 |
23 | object DefaultStringValidator : FieldValidator {
24 | override fun validate(input: String) = input.isNotEmpty()
25 | }
26 |
27 | object DefaultIntValidator : FieldValidator {
28 | override fun validate(input: Int) = input >= 0
29 | }
30 |
31 | fun main() {
32 | Validators.registerValidator(String::class, DefaultStringValidator)
33 | Validators.registerValidator(Int::class, DefaultIntValidator)
34 |
35 | println(Validators[String::class]?.validate("Kotlin"))
36 | println(Validators[Int::class]?.validate(42))
37 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_5Reified/_6RestrictionsOnReifiedTypeParameters.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._5Reified
2 |
3 | // Which of the following calls won't compile?
4 |
5 | //inline fun foo(t: T) {
6 | // bar(t)
7 | //}
8 |
9 | fun bar(t: T) {
10 | // foo(t)
11 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_6LazyEvaluation/_1AsSequence.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._6LazyEvaluation
2 |
3 |
4 | fun main() {
5 |
6 |
7 | val numbers = 1..100_000_000
8 |
9 | numbers.filter { it % 5 == 0 }.take(30)
10 |
11 |
12 | numbers.asSequence().filter { it % 5 == 0 }.take(30)
13 |
14 |
15 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_6LazyEvaluation/_2GenerateSequence.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._6LazyEvaluation
2 |
3 |
4 | fun main() {
5 |
6 |
7 | generateSequence(1) {
8 | it * 10
9 | }.take(300).map { it % 5 }
10 |
11 |
12 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_1AlgebraicDataTypes.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs
2 |
3 |
4 | sealed class Expr {
5 | class Num(val value: Int) : Expr()
6 | class Sum(val left: Expr, val right: Expr) : Expr()
7 | }
8 |
9 | fun eval(e: Expr): Int = when (e) {
10 | is Expr.Num -> e.value
11 | is Expr.Sum -> eval(e.left) + eval(e.right)
12 | }
13 |
14 | fun main() {
15 | // 1 + (2 + 3)
16 | println(eval(Expr.Sum(Expr.Num(1), Expr.Sum(Expr.Num(2), Expr.Num(3)))))
17 | }
18 |
19 |
20 | sealed class Result
21 |
22 | class Success : Result()
23 | class Failure : Result()
24 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_2Currying.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs
2 |
3 |
4 | fun Function2.curry(): (P1) -> (P2) -> R {
5 | return { p1: P1 -> { p2: P2 -> this (p1, p2)}}
6 | }
7 |
8 | fun Function3.curry(): (P1) -> (P2) -> (P3) -> R {
9 | return { p1: P1 -> { p2: P2 -> { p3: P3 -> this (p1, p2, p3)}}}
10 | }
11 |
12 | fun main() {
13 |
14 | val sum = { x: Int, y: Int, z: Int -> x + y + z }
15 |
16 | val sumCurried = sum.curry()
17 |
18 | val result = sumCurried(3)(2)(5)
19 |
20 | println(result)
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_3Partials.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs
2 |
3 |
4 | class Partial
5 |
6 | fun partial(): Partial = Partial()
7 |
8 | fun Function2.createPartialFunction(p1:
9 | P1, partial2: Partial = partial()): (P2) -> R {
10 | return { p2: P2 -> this(p1, p2) }
11 | }
12 |
13 | fun Function2.createPartialFunction(partial1: Partial = partial(),
14 | p2: P2): (P1) -> R {
15 | return { p1: P1 -> this(p1, p2) }
16 | }
17 |
18 |
19 | fun Function5.createPartialFunction(partial1: Partial = partial(),
20 | partial2: Partial = partial(),
21 | partial3: Partial = partial(),
22 | partial4: Partial = partial(),
23 | p5: P5): (P1, P2, P3, P4) -> R {
24 | return { p1: P1, p2: P2, p3: P3, p4: P4 -> this(p1, p2, p3, p4, p5) }
25 | }
26 |
27 | fun Function4.createPartialFunction(partial1: Partial = partial(),
28 | partial2: Partial = partial(),
29 | partial3: Partial = partial(),
30 | p4: P4): (P1, P2, P3) -> R {
31 | return { p1: P1, p2: P2, p3: P3 -> this(p1, p2, p3, p4) }
32 | }
33 |
34 | fun Function3.createPartialFunction(partial1: Partial = partial(),
35 | partial2: Partial = partial(),
36 | p3: P3): (P1, P2) -> R {
37 | return { p1: P1, p2: P2 -> this(p1, p2, p3) }
38 | }
39 |
40 | fun Function3.createPartialFunction(partial1: Partial = partial(),
41 | p2: P2,
42 | partial3: Partial = partial()): (P1, P3) -> R {
43 | return { p1: P1, p3: P3 -> this(p1, p2, p3) }
44 | }
45 |
46 | fun Function3.createPartialFunction(p1: P1,
47 | partial2: Partial = partial(),
48 | p3: P3): (P2) -> R {
49 | return { p2: P2 -> this(p1, p2, p3) }
50 | }
51 |
52 |
53 | fun main() {
54 |
55 | val sum = { x: Int, y: Int -> x + y }
56 |
57 |
58 | val addToTwo = sum.createPartialFunction(2)
59 |
60 |
61 | println(addToTwo(5))
62 |
63 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_4Composition.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs
2 |
3 |
4 | // f(g(x))
5 | fun Function1.compose(g: (RP1) -> FP1): (RP1) -> RF {
6 | return { p1: RP1 -> this(g(p1)) }
7 | }
8 |
9 | fun compose(f: (Int, Int) -> Int, g: (Int) -> Int): (Int, Int) -> Int {
10 | return { p1: Int, p2: Int -> g(f(p1, p2)) }
11 | }
12 |
13 | // g(f(x))
14 | fun Function1.andThen(f: (RG) -> RF1): (GP1) -> RF1 {
15 | return { p1: GP1 -> f(this(p1)) }
16 | }
17 |
18 | fun compose1(f: (a: Any) -> Any, g: (a: Any) -> Any): (a: Any) -> Any {
19 | return { x: Any -> { g(f(x)) } }
20 | }
21 |
22 | fun sum(x: Int, y: Int) = x + y
23 |
24 |
25 | fun squared(x: Int) = x * x
26 |
27 |
28 | fun main() {
29 |
30 |
31 | val sumSquared = compose(::sum, ::squared)
32 |
33 | println(sumSquared(2, 3))
34 |
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_5Functors.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs
2 |
3 |
4 | sealed class Maybe {
5 | object None : Maybe()
6 | data class Just(val value: A) : Maybe()
7 |
8 | inline fun fmap(f: (A) -> B): Maybe = when (this) {
9 | is None -> this
10 | is Just -> Just(f(value))
11 | }
12 | }
13 |
14 |
15 | fun maybeReturnSomething(input: Boolean): Maybe {
16 | return if (input) Maybe.Just(10) else Maybe.None
17 | }
18 |
19 | fun main() {
20 |
21 |
22 | println(Maybe.Just(4).fmap { it + 10 })
23 |
24 |
25 | val someResult: Maybe = maybeReturnSomething(false)
26 | someResult.fmap { it + 10 }
27 |
28 | println(someResult)
29 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_6Applicatives.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs
2 |
3 |
4 | infix fun Maybe<(A) -> B>.apply(f: Maybe): Maybe =
5 | when (this) {
6 | is Maybe.None -> Maybe.None
7 | is Maybe.Just -> f.fmap(this.value)
8 | }
9 |
10 | infix inline fun Array<(A) -> B>.apply(a: Array) =
11 | Array(this.size * a.size) {
12 | this[it / a.size](a[it % a.size])
13 | }
14 |
15 |
16 | fun main() {
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_7Monads.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs
2 |
3 |
4 | sealed class MaybeMonad {
5 | object None : MaybeMonad()
6 | data class Just(val value: A) : MaybeMonad()
7 |
8 | inline fun fmap(f: (A) -> B): MaybeMonad = when (this) {
9 | is None -> this
10 | is Just -> Just(f(value))
11 | }
12 |
13 | infix inline fun bind(f: (A) -> MaybeMonad): MaybeMonad = when (this) {
14 | is None -> this
15 | is Just -> f(value)
16 | }
17 | }
18 |
19 |
20 | fun half(a: Int) = when {
21 | a % 2 == 0 -> MaybeMonad.Just(a / 2)
22 | else -> MaybeMonad.None
23 | }
24 |
25 |
26 | fun main() {
27 | MaybeMonad.Just(20) bind ::half
28 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_8Dsl/_1ExtensionWithInfix.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._8Dsl
2 |
3 |
4 | fun String.toTitleCase(): String {
5 | return this.split(" ").joinToString(" ") { it.capitalize() }
6 | }
7 |
8 |
9 | infix fun String.isTheSameAs(value: String) = this == value
10 |
11 |
12 | fun main() {
13 |
14 |
15 | "Hello".isTheSameAs("Hello")
16 |
17 | "Hello" isTheSameAs "Hello"
18 |
19 |
20 | println("this is a sample string to Title Case it".toTitleCase())
21 | }
22 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_8Dsl/_2Invoke.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._8Dsl
2 |
3 |
4 | class FooClass {
5 | var name: String = ""
6 | operator fun invoke(name: String) {
7 | println("Hello $name")
8 | }
9 | }
10 |
11 |
12 | fun main() {
13 | val foo = FooClass()
14 | foo("Something")
15 | println(foo.name)
16 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_8Dsl/_3LambdasWithReceivers.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._8Dsl
2 |
3 |
4 | fun route(path: String, f: RouteHandler.() -> Unit) {
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_8Dsl/_4DslSample.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._8Dsl
2 |
3 |
4 | class Request(val method: String, val query: String, val contentType: String) {
5 | operator fun invoke(function: () -> Any) {
6 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
7 | }
8 | }
9 |
10 | class Response(var contents: String, var statusCode: Int) {
11 | operator fun invoke(function: () -> Unit): Any {
12 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
13 | }
14 | }
15 |
16 |
17 | class RouteHandler(val request: Request, val response: Response) {}
18 |
19 |
20 | fun get(path: String, f: RouteHandler.() -> Unit): RouteHandler.() -> Unit = f
21 |
22 |
23 | fun String.with(handler: Response.() -> Unit): Pair Unit> = this to handler
24 |
25 |
26 | fun main() {
27 |
28 | get("/home") {
29 | if (request.method == "GET") {
30 | response {
31 |
32 | }
33 | }
34 | }
35 |
36 |
37 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_8Dsl/_5HtmlExample.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._8Dsl
2 |
3 | @DslMarker
4 | annotation class HtmlDsl
5 |
6 | open class Tag(val name: String) {
7 | private val children = mutableListOf()
8 |
9 | protected fun doInit(child: T, init: T.() -> Unit) {
10 | child.init()
11 | children.add(child)
12 | }
13 |
14 | override fun toString() =
15 | "<$name>${children.joinToString("")}$name>"
16 | }
17 |
18 | fun table(init: TABLE.() -> Unit): TABLE {
19 | val table = TABLE()
20 | table.init()
21 | return table
22 | }
23 |
24 | @HtmlDsl
25 | class TABLE : Tag("table") {
26 | fun tr(init: TR.() -> Unit) = doInit(TR(), init)
27 | }
28 |
29 | @HtmlDsl
30 | class TR : Tag("tr") {
31 | fun td(init: TD.() -> Unit) = doInit(TD(), init)
32 | }
33 |
34 | @HtmlDsl
35 | class TD : Tag("td")
36 |
37 | fun createTable(): TABLE {
38 | return table {
39 | tr {
40 | for (i in 1..2) {
41 | td {
42 | }
43 | }
44 | }
45 | }
46 | }
47 |
48 | fun main() {
49 | println(createTable())
50 | //
51 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_9Metaprogramming/_1Annotations.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._9Metaprogramming
2 |
3 |
4 | @Target(AnnotationTarget.CLASS)
5 | annotation class Table(val name: String)
6 |
7 | @Target(AnnotationTarget.PROPERTY)
8 | annotation class Field(val name: String)
9 |
10 |
11 | @Table(name = "ContactTable")
12 | data class Contact(val id: Int, @Field(name = "NAME") val name: String, val email: String)
13 |
14 |
15 | fun main() {
16 |
17 | val annotation = Contact::class.annotations.find { it.annotationClass.simpleName == "Table" }
18 |
19 | println(annotation)
20 |
21 |
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_9Metaprogramming/_2JavaReflection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._9Metaprogramming
2 |
3 | import java.lang.reflect.*
4 |
5 | class Transaction(val id: Int, val amount: Double, var description: String = "Default Value") {
6 | fun validate() {
7 | if (amount > 10000) {
8 | println("org.jetbrains.kotlinworkshop.advanced._9Metaprogramming.Transaction is too large")
9 | }
10 | }
11 | }
12 |
13 | fun introspectInstance(obj: Any) {
14 |
15 | println("Class ${obj.javaClass.simpleName}")
16 | println("Properties\n")
17 | obj.javaClass.declaredFields.forEach {
18 | println("${it.name} of type ${it.type}")
19 | }
20 | println("Functions\n")
21 | obj.javaClass.declaredMethods.forEach {
22 | println("${it.name}")
23 | }
24 |
25 | }
26 |
27 | fun getType(obj: Type) {
28 | println(obj.typeName)
29 | }
30 |
31 | fun main() {
32 | getType(Transaction::class.java)
33 |
34 | // introspectInstance(Transaction(1, 200.0, "A simple transaction"))
35 | }
--------------------------------------------------------------------------------
/instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_9Metaprogramming/_3KotlinReflection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.advanced._9Metaprogramming
2 |
3 | import kotlin.reflect.*
4 |
5 | fun getKotlinType(obj: KClass<*>) {
6 | println(obj.qualifiedName)
7 | }
8 |
9 | fun main() {
10 |
11 |
12 | /*
13 | val classInfo = Transaction::class
14 |
15 | classInfo.memberProperties.forEach {
16 | println("Property ${it.name} of type ${it.returnType}")
17 | }
18 |
19 | classInfo.constructors.forEach {
20 | println("Constructor ${it.name} - ${it.parameters}")
21 | }
22 |
23 | getKotlinType(Transaction::class)
24 | */
25 |
26 | val constructor = ::Transaction
27 |
28 | println(constructor)
29 |
30 |
31 | val idParam = constructor.parameters.first { it.name == "id" }
32 | val amountParam = constructor.parameters.first { it.name == "amount" }
33 |
34 | val transaction = constructor.callBy(mapOf(idParam to 1, amountParam to 2000))
35 |
36 | val trans = Transaction(1, 20.0, "New Value")
37 |
38 |
39 | val nameProperty = Transaction::class.members.find { it.name == "description" }
40 |
41 | }
--------------------------------------------------------------------------------
/instructor/introduction/cmdline/Hello.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kotlin/workshop/37552440e6e6a1f7607ea5722eef1e8d5578d4f5/instructor/introduction/cmdline/Hello.class
--------------------------------------------------------------------------------
/instructor/introduction/cmdline/Hello.java:
--------------------------------------------------------------------------------
1 | public class Hello {
2 | public static void main(String[] args) {
3 | System.out.println("Hello, World!");
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/instructor/introduction/cmdline/HelloKt.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kotlin/workshop/37552440e6e6a1f7607ea5722eef1e8d5578d4f5/instructor/introduction/cmdline/HelloKt.class
--------------------------------------------------------------------------------
/instructor/introduction/cmdline/Hellokt.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kotlin/workshop/37552440e6e6a1f7607ea5722eef1e8d5578d4f5/instructor/introduction/cmdline/Hellokt.jar
--------------------------------------------------------------------------------
/instructor/introduction/cmdline/META-INF/main.kotlin_module:
--------------------------------------------------------------------------------
1 |
2 |
3 | HelloKt
--------------------------------------------------------------------------------
/instructor/introduction/cmdline/hello.kt:
--------------------------------------------------------------------------------
1 | fun main() {
2 | println("Hello, World!")
3 | }
4 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_10Conventions/_1OperatorOverloading.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._10Conventions
2 |
3 | import java.lang.*
4 |
5 |
6 | data class Time(val hours: Int, val mins: Int) {
7 | operator fun plus(time: Time): Time {
8 | val minutes = this.mins + time.mins
9 | val hoursInMinutes = minutes / 60
10 | val remainingMinutes = minutes % 60
11 | val hours = this.hours + time.hours + hoursInMinutes
12 | return Time(hours, remainingMinutes)
13 | }
14 | }
15 |
16 | operator fun StringBuilder.plus(stringBuilder: StringBuilder) {
17 | stringBuilder.forEach { this.append(it) }
18 | }
19 |
20 | data class Point(val x: Int, val y: Int)
21 |
22 | operator fun Point.plus(other: Point): Point {
23 | return Point(x + other.x, y + other.y)
24 | }
25 |
26 | operator fun Point.times(scale: Int): Point {
27 | return Point(x * scale, y * scale)
28 | }
29 |
30 | fun main() {
31 |
32 | val newTime = Time(10, 40) + Time(3, 20)
33 |
34 | println(newTime)
35 |
36 | val sb = StringBuilder()
37 | for (str in sb) {
38 | str + "Value"
39 | }
40 |
41 | val p1 = Point(1, 2) + Point(2, 3)
42 | val p2 = Point(1, 2) * 3
43 | println(p1)
44 | println(p2)
45 |
46 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_11Generics/_1Basics.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._11Generics
2 |
3 | import org.jetbrains.kotlinworkshop.introduction._Shared.*
4 |
5 |
6 | interface Repository {
7 | fun getById(id: Int): T
8 | fun getAll(): List
9 | }
10 |
11 | fun main() {
12 |
13 | val customerRepo = CustomerRepository()
14 |
15 | val customer = customerRepo.getById(10)
16 | val customers = customerRepo.getAll()
17 |
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_11Generics/_2Invariance.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._11Generics
2 |
3 |
4 | fun invariant() {
5 | val elements: MutableList
6 | val strings: MutableList = mutableListOf("A", "B", "C")
7 |
8 | // The line below won't compile
9 |
10 | // elements = strings
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_11Generics/_3Covariance.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._11Generics
2 |
3 |
4 | class Consumer {
5 | fun consumeSomething(list: List) {
6 |
7 | }
8 | }
9 |
10 |
11 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_11Generics/_4Contravariance.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._11Generics
2 |
3 | class Producer {
4 | fun produceSomething(): List {
5 | TODO()
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_0Main.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._1Intro
2 |
3 | fun main(args: Array) {
4 | val name = if (args.size > 0) args[0] else "Kotlin"
5 | println("Hello, $name!")
6 |
7 | // ${}
8 | }
9 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_1Variables.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._1Intro
2 |
3 | fun main() {
4 | // read-only
5 | val question: String =
6 | "life, the universe, " +
7 | "and everything"
8 | println("$question?")
9 |
10 | // mutable
11 | var answer = 0
12 | answer = 42
13 | println(answer)
14 |
15 | // answer = "no answer"
16 |
17 | // val is read-only reference, not object
18 | val languages = mutableListOf("Java")
19 | languages.add("Kotlin")
20 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_2Numbers.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._1Intro
2 |
3 |
4 | fun main() {
5 |
6 | val myLong = 10L
7 | val myFloat = 100F
8 | val myHex = 0x0F
9 | val myBinary = 0b01
10 |
11 | val myInt = 100
12 | val myLongAgain: Long = myInt.toLong()
13 |
14 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_3Functions.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._1Intro
2 |
3 | fun max(a: Int, b: Int): Int {
4 | return if (a < b) a else b
5 | }
6 |
7 | fun max2(a: Int, b: Int) = if (a < b) a else b
8 |
9 | // default values for arguments
10 | fun sum(a: Int, b: Int, c: Int = 0) = a + b + c
11 |
12 |
13 | // vararg
14 | fun printMany(vararg elements: Int) {
15 | for (element in elements) {
16 | println(element)
17 | }
18 |
19 | doSomething(*elements)
20 |
21 | }
22 |
23 | fun doSomething(vararg elements: Int) {
24 | for (element in elements) {
25 | println("Doing something $element")
26 | }
27 | }
28 |
29 | fun main() {
30 | sum(1, 2)
31 | sum(1, 2, 3)
32 | // named arguments
33 | sum(b = 2, a = 1)
34 |
35 | printMany(1, 2, 3, 4, 5)
36 | }
37 |
38 |
39 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_4LocalFunctions.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._1Intro
2 |
3 |
4 | fun foo(fooParam: String) {
5 |
6 | val outerFunction = "Value"
7 | fun bar(barParam: String) {
8 |
9 | println(barParam)
10 | println(fooParam)
11 | println(outerFunction)
12 | }
13 |
14 |
15 | }
16 |
17 | fun main() {
18 |
19 | foo("Some value")
20 |
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_5Constants.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._1Intro
2 |
3 |
4 | val CopyrightName = "JetBrains"
5 |
6 | // known at compile time
7 | const val CopyrightYear = 2017
8 |
9 |
10 | val a = sum(2, 3)
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_6BasicInterop.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._1Intro
2 |
3 | import org.jetbrains.kotlinworkshop.introduction._Shared.*
4 |
5 |
6 | fun main() {
7 |
8 | val customerJava = CustomerJava(1, "Mary Jane")
9 | customerJava.name
10 |
11 |
12 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_7FromJava.java:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._1Intro;
2 |
3 | import org.jetbrains.kotlinworkshop.introduction._Shared.Customer;
4 |
5 | public class _7FromJava {
6 |
7 | public static void main(String[] args) {
8 |
9 | Customer customerKotlin = new Customer(1, "Mary Jane");
10 |
11 | //
12 | int result = _3FunctionsKt.max(2, 3);
13 |
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_2ControlStructures/_1IfAndWhen.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._2ControlStructures
2 |
3 |
4 | enum class Color {
5 | BLUE, ORANGE, RED
6 | }
7 |
8 | fun updateWeather(
9 | celsiusDegrees: Double
10 | ) {
11 | val description: String
12 | val color: Color
13 | when {
14 | celsiusDegrees < 0 -> {
15 | description = "cold"
16 | color = Color.BLUE
17 | }
18 | celsiusDegrees in 0..15 -> {
19 | description = "mild"
20 | color = Color.ORANGE
21 | }
22 | else -> {
23 | description = "hot"
24 | color = Color.RED
25 | }
26 | }
27 | }
28 |
29 | fun updateWeather1(celsiusDegrees: Double) {
30 | val (description, color) =
31 | when {
32 | celsiusDegrees < 0 -> Pair("cold", Color.BLUE)
33 | celsiusDegrees in 0..15 -> "mild" to Color.ORANGE
34 | else -> "hot" to Color.RED
35 | }
36 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_2ControlStructures/_2Loops.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._2ControlStructures
2 |
3 | fun whileLoop() {
4 | fun condition() = true
5 |
6 | while (condition()) {
7 | /*...*/
8 | }
9 |
10 | do {
11 | /*...*/
12 | } while (condition())
13 | }
14 |
15 |
16 | fun forLoop() {
17 | val list = listOf(1, 2, 3)
18 | for (element in list) {
19 | print(element)
20 | }
21 |
22 | for (i in 1..9) { // including 9
23 | print(i)
24 | }
25 |
26 | // excluding 10 (the same as 1..9)
27 | for (i in 1 until 10) {
28 | print(i)
29 | }
30 |
31 | for (i in 9 downTo 1 step 2) {
32 | print(i)
33 | }
34 | }
35 |
36 | fun main() {
37 | forLoop()
38 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_2ControlStructures/_3Iterating.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._2ControlStructures
2 |
3 | fun iteratingOverCollection() {
4 | val list = listOf("a", "b")
5 | for (s in list) {
6 | println(s)
7 | }
8 | }
9 |
10 | fun iteratingOverMap() {
11 | val map = mapOf(1 to "one", 2 to "two", 3 to "three")
12 |
13 | for ((key, value) in map) {
14 | println("$key = $value")
15 | }
16 | }
17 |
18 | fun iteratingOverCollectionWithIndex() {
19 | for ((index, element) in listOf("a", "b", "c").withIndex()) {
20 | println("$index $element")
21 | }
22 | }
23 |
24 | fun main() {
25 | iteratingOverCollection()
26 | iteratingOverMap()
27 | iteratingOverCollectionWithIndex()
28 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_2ControlStructures/_4Ranges.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._2ControlStructures
2 |
3 | fun isLetter(c: Char) = c in 'a'..'z' || c in 'A'..'Z'
4 | // c in 'a'..'z'
5 | // is compiled to:
6 | // 'a' <= c && c <= 'z'
7 |
8 | fun isNotDigit(c: Char) = c !in '0'..'9'
9 |
10 | fun main() {
11 | println(isLetter('q')) // true
12 | println(isNotDigit('x')) // true
13 | }
14 |
15 | fun recognize(c: Char) = when (c) {
16 | in '0'..'9' -> "It's a digit!"
17 | in 'a'..'z', in 'A'..'Z' -> "It's a letter!"
18 | else -> "I don't know…"
19 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_10NestedClasses.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._3Classes
2 |
3 |
4 | class Outer {
5 | private val bar: Int = 1
6 |
7 | class Nested {
8 | fun foo() = 2
9 | }
10 | }
11 |
12 | val outer = Outer.Nested().foo() // == 2
13 |
14 | class OuterWithInner {
15 | private val bar: Int = 1
16 |
17 | inner class Inner {
18 | fun foo() = bar
19 | }
20 | }
21 |
22 | val outerWithInner = OuterWithInner().Inner().foo() // == 1
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_11TypeAliases.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._3Classes
2 |
3 |
4 | typealias CustomerName = String
5 |
6 |
7 | // Example of using typealias for rename with @Deprecated
8 |
9 |
10 | class BaseCustomer // before was called BasicCustomer
11 |
12 | @Deprecated("BasicCustomer is now called BaseCustomer", replaceWith = ReplaceWith("BaseCustomer"))
13 | typealias BasicCustomer = BaseCustomer
14 |
15 |
16 |
17 |
18 | fun main() {
19 |
20 |
21 | val customer = BasicCustomer()
22 |
23 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_1Classes.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._3Classes
2 |
3 | // similar to javaCode.Person
4 |
5 | class AnotherPerson(val name: String, val age: Int)
6 |
7 | fun main() {
8 | // no new keyword, constructor is called as a regular function
9 | val person = AnotherPerson("Alice", 26)
10 | println(person.name)
11 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_2PrimaryConstructor.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._3Classes
2 |
3 | /* short syntax */
4 | class Person1(val name: String)
5 |
6 | /* full syntax */
7 | // constructor parameter
8 | class Person2(name: String) {
9 |
10 | // property
11 | val name: String
12 |
13 | // constructor body
14 | init {
15 | this.name = name
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_3Constructors.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._3Classes
2 |
3 | class Rectangle(val height: Int, val width: Int) {
4 |
5 | //secondary constructors
6 | constructor(side: Int) : this(side, side)
7 | }
8 |
9 | fun main() {
10 | val rectangle = Rectangle(42)
11 | println(rectangle.height == rectangle.width)
12 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_4Properties.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._3Classes
2 |
3 | class AnotherRectangle(val height: Int, val width: Int) {
4 |
5 | // you can redefine getter (and setter)
6 | val isSquare: Boolean
7 | get() {
8 | return height == width
9 | }
10 | }
11 |
12 | fun main() {
13 | val rectangle = AnotherRectangle(41, 43)
14 | println(rectangle.isSquare)
15 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_5MutableProperty.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._3Classes
2 |
3 | class LengthCounter {
4 | var counter: Int = 0
5 | private set
6 |
7 | fun addWord(word: String) {
8 | counter += word.length
9 | }
10 | }
11 |
12 | fun main() {
13 | val lengthCounter = LengthCounter()
14 | lengthCounter.addWord("Hi!")
15 | println(lengthCounter.counter)
16 |
17 | StateLogger().state = true
18 | }
19 |
20 | class StateLogger {
21 | var state = false
22 | set(value) {
23 | println("state has changed")
24 | field = value
25 | }
26 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_6Equals.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._3Classes
2 |
3 | fun main() {
4 | val set1 = setOf(1, 2, 3)
5 | val set2 = setOf(1, 2, 3)
6 |
7 | // checks reference equality
8 | println(set1 === set2)
9 |
10 | // calls equals
11 | println(set1 == set2)
12 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_7Tuples.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._3Classes
2 |
3 |
4 | fun main() {
5 |
6 | val countryAndCity = Pair("Spain", "Madrid")
7 |
8 | countryAndCity.first
9 | countryAndCity.component1()
10 |
11 | val countryAndCityAndContinent = Triple("Spain", "Madrid", "Europe")
12 |
13 |
14 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_8DataClass.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._3Classes
2 |
3 | // Adding data makes the compiler generate useful methods
4 | // such as equals, hashCode, toString.
5 | data class Person(
6 | val name: String,
7 | val age: Int)
8 |
9 | fun main() {
10 | val person1 = Person("Alice", 21)
11 | val person2 = Person("Alice", 21)
12 | println(person1)
13 | println(person1 == person2)
14 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_9Destructuring.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._3Classes
2 |
3 |
4 | fun main() {
5 |
6 | val (country, city) = Pair("Spain", "Madrid")
7 |
8 |
9 | val (country1, city1, continent1) = Triple("Spain", "Madrid", "Europe")
10 |
11 | val (_, age) = Person("Joe Smith", 42)
12 |
13 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/javaCode/Person.java:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._3Classes.javaCode;
2 |
3 | public class Person {
4 | private final String name;
5 | private final int age;
6 |
7 | public Person(String name, int age) {
8 | this.name = name;
9 | this.age = age;
10 | }
11 |
12 | public String getName() {
13 | return name;
14 | }
15 |
16 | public int getAge() {
17 | return age;
18 | }
19 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/javaCode/Rectangle.java:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._3Classes.javaCode;
2 |
3 | public class Rectangle {
4 | private final int width;
5 | private final int height;
6 |
7 | public Rectangle(int width, int height) {
8 | this.width = width;
9 | this.height = height;
10 | }
11 |
12 | public int getWidth() {
13 | return width;
14 | }
15 |
16 | public int getHeight() {
17 | return height;
18 | }
19 |
20 | public boolean isSquare() {
21 | return width == height;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_4Hierarchies/_1Interfaces.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._4Hierarchies
2 |
3 | import org.jetbrains.kotlinworkshop.introduction._Shared.*
4 |
5 | interface CustomerRepository {
6 | val isEmpty: Boolean
7 | get() = true
8 |
9 | fun store(obj: Customer) {
10 | // implement code to store
11 | }
12 |
13 | fun getById(id: Int): Customer
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_4Hierarchies/_2AbstractClasses.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._4Hierarchies
2 |
3 |
4 | abstract class StoredEntity {
5 | val isActive = true
6 | abstract fun store()
7 | fun status(): String {
8 | return isActive.toString()
9 | }
10 |
11 | }
12 |
13 | class Employee : StoredEntity() {
14 | override fun store() {
15 | throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
16 | }
17 |
18 | }
19 |
20 |
21 | fun main() {
22 | val se = Employee()
23 | se.isActive
24 | se.status()
25 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_4Hierarchies/_3ClassInheritance.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._4Hierarchies
2 |
3 |
4 | open class Person() {
5 | open fun validate() {
6 |
7 | }
8 | }
9 |
10 | open class OpenCustomer() : Person() {
11 | final override fun validate() {
12 |
13 | }
14 | }
15 |
16 | class SpecialCustomer : OpenCustomer() {
17 |
18 | }
19 |
20 | data class CustomerEntity(val name: String) : Person()
21 |
22 | fun main() {
23 |
24 | val customer = OpenCustomer()
25 |
26 | customer.validate()
27 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_5Nullability/_1Nullability.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._5Nullability
2 |
3 | fun main() {
4 |
5 | val s1: String = "always not null"
6 | val s2: String? = null
7 |
8 | val i1: Int = s1.length
9 | // s2.length
10 |
11 | if (s2 != null) s2.length
12 | s2?.length
13 |
14 | val i2: Int? = if (s2 != null) s2.length else null
15 | val i3: Int? = s2?.length
16 |
17 | val i4: Int? = if (s2 != null) s2.length else 0
18 | val i5: Int = s2?.length ?: 0
19 |
20 | s2!!
21 | }
22 |
23 | fun test1(s: String?) {
24 | if (s == null) return
25 | s.length
26 | }
27 |
28 | fun test2(s: String?) {
29 | if (s == null) fail()
30 | s.length
31 | }
32 |
33 | fun test3(s: String?) {
34 | val i: Int = s?.length ?: fail()
35 | }
36 |
37 | fun fail(): Nothing =
38 | throw UnsupportedOperationException()
39 |
40 | fun notImplemented() {
41 | TODO()
42 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_5Nullability/_2Safecast.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._5Nullability
2 |
3 | class A(val value: Int)
4 |
5 | fun foo(a: Any?) = (a as? A)?.value
6 |
7 | fun main() {
8 | println(foo(A(42))) // 42
9 | println(foo(42)) // null
10 | println(foo(null)) // null
11 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_5Nullability/_3LateInit.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._5Nullability
2 |
3 |
4 | class Dependency
5 | class Consumer {
6 | lateinit var dependency: Dependency
7 |
8 | fun usingDependency() {
9 |
10 | }
11 |
12 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_6Extensions/_1Extensions.kt:
--------------------------------------------------------------------------------
1 | //@file:JvmName("StringUtil")
2 | package org.jetbrains.kotlinworkshop.introduction._6Extensions
3 |
4 | fun String.lastChar() =
5 | this.get(this.length - 1)
6 |
7 | // 'this' can be omitted
8 | fun String.lastChar1() =
9 | get(length - 1)
10 |
11 | fun test() {
12 | // visible in completion
13 | "abc".lastChar()
14 | }
15 |
16 | // Infix
17 | infix fun String.isEqual(value: String) = this == value
18 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_7Lambdas/_1HigherOrder.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._7Lambdas
2 |
3 |
4 | fun higherOrder(value: String, op: (String) -> String): String {
5 | println("Executing the operation $op")
6 | return op(value)
7 | }
8 |
9 | fun lowerCase(value: String) = value.toLowerCase()
10 |
11 | fun main() {
12 | println(higherOrder("HELLO", ::lowerCase))
13 | }
14 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_7Lambdas/_2Lambdas.kt:
--------------------------------------------------------------------------------
1 | package lambdas
2 |
3 | fun basicSyntax() {
4 | val sum = { x: Int, y: Int -> x + y }
5 |
6 | val sum1: (Int, Int) -> Int = { x, y -> x + y }
7 |
8 | println(sum(1, 2)) // 3
9 | }
10 |
11 | fun shortSyntax() {
12 | val string = "one, two, three"
13 |
14 | println(string.filter({ c: Char -> c in 'a'..'z' })) // "onetwothree"
15 |
16 | string.filter() { c: Char -> c in 'a'..'z' }
17 |
18 | string.filter { c: Char -> c in 'a'..'z' }
19 |
20 | string.filter { c -> c in 'a'..'z' }
21 |
22 | string.filter { it in 'a'..'z' }
23 |
24 | string.filter {
25 | it in 'a'..'z'
26 | }
27 |
28 | val s = "abCDa"
29 |
30 | println(s.filter { it in 'a'..'z' }) // aba
31 | println(s.count { it in 'a'..'z' }) //3
32 |
33 | "abCDa".any { it in '1'..'9' } // false
34 | "abCDa1".any { it in '1'..'9' } // true
35 | // true if there at least one character satisfying the predicate
36 |
37 | "abCDa".all { it.toInt() < 200 }
38 | "abd33".find { it > 'c' } // d
39 |
40 | for ((index, ch) in "abc".withIndex()) {
41 |
42 | }
43 |
44 | println("abcd".zip("1234"))
45 |
46 | "abCDa".any { it in 'a'..'z' }
47 | "abCDa".count { it in 'a'..'z' }
48 | "abCDa".find { it in 'a'..'z' }
49 | "abCDa".zip("79371").joinToString()
50 | }
51 |
52 | fun main() {
53 | basicSyntax()
54 | shortSyntax()
55 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_7Lambdas/_3DestructuringInLambdas.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._7Lambdas
2 |
3 | fun main() {
4 | val map = mapOf(1 to "one", 2 to "two")
5 | map.forEach { entry ->
6 | val (key, value) = entry
7 | println(value)
8 | }
9 | map.forEach { (key, value) ->
10 | println(value)
11 | }
12 | map.forEach { (_, value) ->
13 | println(value)
14 | }
15 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_7Lambdas/_4AnonymousFunctions.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._7Lambdas
2 |
3 |
4 | fun op(x: Int, op: (Int) -> Int): Int {
5 |
6 | return op(x)
7 | }
8 |
9 | fun main() {
10 |
11 | op(3, { x -> x * x })
12 |
13 | op(2, fun(x): Int {
14 |
15 | if (x > 10) {
16 | return 0
17 | } else {
18 | return x * x
19 | }
20 |
21 | })
22 |
23 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_8Delegation/_1ClassDelegation.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._8Delegation
2 |
3 | import org.jetbrains.kotlinworkshop.introduction._Shared.*
4 |
5 |
6 | interface Repository {
7 | fun getById(id: Int): Customer
8 | fun getAll(): List
9 | }
10 |
11 | interface Logger {
12 | fun logAll()
13 | }
14 |
15 | class Controller(repository: Repository, logger: Logger) : Repository by repository, Logger by logger {
16 |
17 |
18 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_8Delegation/_2LazyProperty.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._8Delegation
2 |
3 | class LazyProperty {
4 | val lazy: Int by lazy {
5 | println("Calculate the value")
6 | 42
7 | }
8 | }
9 |
10 | fun main() {
11 | println("--- creation ---")
12 | val property = LazyProperty()
13 |
14 | println("--- first access ---")
15 | property.lazy
16 |
17 | println("--- second access ---")
18 | property.lazy
19 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_8Delegation/_3Observable.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._8Delegation
2 |
3 | import kotlin.properties.*
4 | import kotlin.reflect.*
5 |
6 | class Person(
7 | val name: String, age: Int, salary: Int
8 | ) {
9 | private val observer = {
10 | prop: KProperty<*>, oldValue: Int, newValue: Int ->
11 | println("Property value $oldValue has changed to $newValue")
12 | }
13 | var age: Int by Delegates.observable(age, observer)
14 | var salary: Int by Delegates.observable(salary, observer)
15 | }
16 |
17 | fun main() {
18 | val person = Person("Alice", 25, 2000)
19 | person.age++
20 | person.salary += 100
21 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_8Delegation/_4CustomDelegation.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._8Delegation
2 |
3 | import kotlin.reflect.*
4 |
5 |
6 | class Service {
7 |
8 | var someProperty: String by ExternalFunctionality()
9 |
10 |
11 | }
12 |
13 | class ExternalFunctionality {
14 |
15 | var backingField = "Default"
16 | operator fun getValue(service: Service, property: KProperty<*>): String {
17 | println("getValue called with params: \n" +
18 | "service: $service\n" +
19 | "property: ${property.name}"
20 | )
21 | return backingField
22 | }
23 |
24 | operator fun setValue(service: Service, property: KProperty<*>, value: String) {
25 | backingField = value
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_1ListOperators.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._9Functional
2 |
3 |
4 | fun head(list: List): T {
5 | return when (list.count()) {
6 | 0 ->
7 | throw IllegalArgumentException("Cannot ask for head on empty list")
8 | else -> list[0]
9 | }
10 | }
11 |
12 |
13 | fun cons(element: T, list: List): List {
14 | return when (list.count()) {
15 | 0 -> listOf(element)
16 | 1 -> listOf(element, head(list))
17 | else -> listOf(element).plus(list)
18 | }
19 | }
20 |
21 |
22 | fun tail(list: List): List {
23 | return when (list.count()) {
24 | 0 -> throw IllegalArgumentException("Cannot ask for tail on empty list")
25 | 1 -> emptyList()
26 | else -> list.drop(1)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_2Folds.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._9Functional
2 |
3 |
4 | fun maxNumbers(list: List): Int {
5 | when (list.count()) {
6 | 0 -> throw IllegalArgumentException("This list is empty")
7 | 1 -> return list[0]
8 | else -> return Math.max(list[0], maxNumbers(tail(list)))
9 |
10 | }
11 | }
12 |
13 |
14 | fun maxNumbersFold(list: List): Int {
15 | return list.fold(0, { x, y -> Math.max(x, y) })
16 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_3RefactoringFunctional.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._9Functional
2 |
3 |
4 | fun itDoesSomething(elements: List): HashMap {
5 | var i = 0
6 | val results = hashMapOf()
7 | while (i < elements.size) {
8 | val element = results[elements[i]]
9 | if (element != null) {
10 | results[elements[i]] = element + 1
11 | } else {
12 | results[elements[i]] = 1
13 | }
14 | i++
15 | }
16 | return results
17 | }
18 |
19 |
20 | fun itDoesSomethingAlso(elements: List): List> {
21 | return elements.groupBy {
22 | it
23 | }.map {
24 | Pair(it.key, it.value.count())
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_4RemovingState.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._9Functional
2 |
3 | import org.jetbrains.kotlinworkshop.introduction._Shared.*
4 |
5 |
6 | // Removing for Loop
7 |
8 | fun topAlbums_v1(albums: List): List {
9 | val hits = arrayListOf()
10 | for (album in albums) {
11 | if (album.chartUK == 1 || album.chartUS == 1) {
12 | hits.add(album)
13 | }
14 | }
15 | return hits
16 | }
17 |
18 | // Moving towards a functional approach (passing moving part)
19 |
20 | fun topAlbums_v2(albums: List): List {
21 | val hits = arrayListOf()
22 | albums.forEach { album ->
23 | if (album.chartUK == 1 || album.chartUS == 1) {
24 | hits.add(album)
25 | }
26 | }
27 | return hits
28 | }
29 |
30 | // Clean up
31 |
32 | fun topAlbums_v3(albums: List): List {
33 | val hits = arrayListOf()
34 | albums.forEach {
35 | if (it.chartUK == 1 || it.chartUS == 1) {
36 | hits.add(it)
37 | }
38 | }
39 | return hits
40 | }
41 |
42 | // Focusing on actual intent
43 |
44 | fun topAlbums_v4(albums: List): List {
45 | return albums.filter { album ->
46 | (album.chartUK == 1 || album.chartUS == 1)
47 | }
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_5TransformingData.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._9Functional
2 |
3 | import org.jetbrains.kotlinworkshop.introduction._Shared.*
4 |
5 |
6 | // Adding an intermediate structure
7 |
8 | fun hitYears_v1(albums: List): List {
9 | val hits = albums.filter { it.chartUS == 1 || it.chartUK == 1 }
10 | val years = arrayListOf()
11 | hits.forEach {
12 | years.add(it.year)
13 | }
14 | return years
15 | }
16 |
17 | // Using transformation functions
18 |
19 | fun hitYears_v2(albums: List): List {
20 | return albums.filter { it.chartUS == 1 || it.chartUK == 1 }.map { it.year }
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_6VariousPatterns.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._9Functional
2 |
3 |
4 | data class Customer(val id: String, val name: String, val type: String, val country: String)
5 |
6 |
7 | // Filter Pattern
8 | class CustomerFilter {
9 | fun filterByName(customers: List, name: String): List {
10 | val matchedCustomers = arrayListOf()
11 | for (customer in customers) {
12 | if (customer.name == name) {
13 | matchedCustomers.add(customer)
14 | }
15 | }
16 | return matchedCustomers
17 | }
18 |
19 | fun filterByCountry(customers: List, country: String): List {
20 | val matchedCustomers = arrayListOf()
21 | for (customer in customers) {
22 | if (customer.country == country) {
23 | matchedCustomers.add(customer)
24 | }
25 | }
26 | return matchedCustomers
27 | }
28 | }
29 |
30 |
31 | // Strategy Pattern
32 | interface SortAlgorithm {
33 | fun > sort(list: List): List
34 | }
35 |
36 | class QuickSort : SortAlgorithm {
37 | override fun > sort(list: List): List {
38 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
39 | }
40 | }
41 |
42 | class BubbleSort : SortAlgorithm {
43 | override fun > sort(list: List): List {
44 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
45 | }
46 |
47 | }
48 |
49 |
50 | // Template Patterns
51 | abstract class Record {
52 | abstract fun edit()
53 | abstract fun save()
54 | fun checkPermissions() {
55 |
56 | }
57 |
58 | fun modify() {
59 | checkPermissions()
60 | edit()
61 | save()
62 | }
63 | }
64 |
65 | class CustomerRecord : Record() {
66 | override fun edit() {
67 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
68 | }
69 |
70 | override fun save() {
71 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
72 | }
73 |
74 | }
75 |
76 | class InvoiceRecord : Record() {
77 | override fun edit() {
78 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
79 | }
80 |
81 | override fun save() {
82 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
83 | }
84 |
85 | }
86 |
87 |
88 | // Clean-ups > using statement
89 |
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_7TailRecursion.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._9Functional
2 |
3 |
4 | fun factorial(number: Int): Int {
5 | when (number) {
6 | 0, 1 -> return 1
7 | else -> return number * factorial(number - 1)
8 | }
9 | }
10 |
11 |
12 | tailrec fun factorialTR(number: Int, accumulator: Int = 1): Int {
13 | when (number) {
14 | 0 -> return accumulator
15 | else -> return factorialTR(number - 1, accumulator * number)
16 | }
17 | }
18 |
19 |
20 | fun main() {
21 | println(factorial(5))
22 | println(factorialTR(5))
23 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_8Memoisation.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._9Functional
2 |
3 |
4 | fun fibonnaciRecursive(n: Long): Long {
5 | return when (n) {
6 | 0L, 1L -> n
7 | else -> fibonnaciRecursive(n - 1) + fibonnaciRecursive(n - 2)
8 | }
9 | }
10 |
11 | fun fibonacciIterative(n: Long): Long {
12 | var a = 0L
13 | var b = 1L
14 | for (i in 0..n - 1) {
15 | val temp = a
16 | a = b
17 | b = temp + a
18 | }
19 | return a
20 | }
21 |
22 |
23 | val cache = hashMapOf(0L to 0L, 1L to 1L)
24 |
25 | fun fibonacciMemoised(n: Long): Long {
26 | return if (cache.containsKey(n)) {
27 | cache.getValue(n)
28 | } else {
29 | val result = fibonacciMemoised(n - 1) + fibonacciMemoised(n - 2)
30 | cache[n] = result
31 | result
32 | }
33 | }
34 |
35 | fun main() {
36 | println(fibonacciMemoised(560))
37 | }
--------------------------------------------------------------------------------
/instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_Shared/AlbumData.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.kotlinworkshop.introduction._Shared
2 |
3 |
4 | data class Album(val title: String, val year: Int, val chartUK: Int, val chartUS: Int, val tracks: List