forked from gosu-lang/gosu-lang.github.com
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdocs.html
1045 lines (843 loc) · 38.8 KB
/
docs.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
---
layout: main
---
<!-- Getting Started -->
<section id="getting-started">
<div class="page-header">
<h1>Getting Started</h1>
</div>
<p>There are several options to get started with Gosu depending on your needs</p>
<h2>Gosu Lab</h2>
<p>Gosu Lab is the easiest way to experiment with Gosu:</p>
<ul>
<li><a href="downloads.html">Download</a> the latest Gosu distribution</li>
<li><a href="https://www.google.com/search?q=how+to+set+java_home+on+windows">Set </a>the <code>JAVA_HOME</code>environment variable to JDK 1.8's home, if needed</li>
<li>Unzip the distribution zip, go to the bin folder and double click on gosu.cmd (or gosu if you are using Linux/Mac)</li>
</ul>
<p>You can try the bundled example projects like the Life game. Just select Life from the Examples pane and run the game by pressing F5.</p>
<h2>Gosu Plugin for IntelliJ</h2>
<p>The <a href="intellij.html">Gosu Plugin for IntelliJ</a> is the recommended way to use Gosu. Keep in mind, however, the latest new language features may not yet be supported in the IntelliJ plugin. If this is the case and you want to experiment with new features, use the Gosu Lab IDE instead (see instructions above).</p>
<p>The plugin is hosted on the IntelliJ IDEA Plugin Repository and you can download it directly from within
IntelliJ IDEA. If you installed the old 3.X plugin, delete the plugin and remove the Gosu SDK (File > Project Structure > SDKs), the new plugin does not need it.</p>
<h2>Maven and Gradle</h2>
<p>If Maven is your thing, here is a simple <a href="https://github.com/gosu-lang/example-gosuc-simple/archive/master.zip">starter project</a>. Run <code>mvn test</code> to execute the JUnit tests contained within.</p>
<p>Gosu also plays nicely with Gradle - here is another simple <a href="https://github.com/gosu-lang/example-gradle-simple/archive/master.zip">starter project</a>. Run <code>gradlew test</code> to execute the JUnit tests contained within.</p>
<p>It is noteworthy that Maven and Gradle projects do not require a local Gosu installation - the respective dependency resolution strategies will download the appropriate Gosu JARs from Maven Central.</p>
<h2>...and More</h2>
<p>Alternatively, a downloadable archive of simple command-line examples is available <a href="https://github.com/gosu-lang/example-commandline/archive/master.zip">here</a>. Check the README file for instructions or view the <a href="https://github.com/gosu-lang/example-commandline">source</a>.</p>
<p>For the truly impatient, you can evaluate some simple gosu expressions online over on the <a href="/play.html">Play</a> page.</p>
</section>
<section id="basics">
<div class="page-header">
<h1>The Basics</h1>
</div>
<h2>Variables and Type Declarations</h2>
<p>Gosu is statically typed, but uses type inference to eliminate the vast majority of syntax overhead usually
involved with static typing.</p>
<p>Check it out:</p>
<pre class="prettyprint">
var foo = "Foo" // a String
var one = 1 // a Number
var guess : String = null // Must declare the type because it can't be inferred
</pre>
<h2>Operators</h2>
<p>Gosu supports the standard Java operators, with a few minor restrictions and some great bonuses:</p>
<ul>
<li><code>++</code> / <code>--</code> - Just like the Java operators, except they cannot be used within another statement</li>
<li><code>==</code> - Tests for object equality, just like <code>.equals()</code></li>
<li><code>===</code> - Tests for <em>instance</em> equality</li>
<li><code><></code> - The same as <code>!=</code></li>
<li><code><</code>,<code>></code>, etc - Standard comparison semantics which also works on <code>java.lang.Comparable</code> objects</li>
</ul>
<h2>Loops</h2>
<p>Gosu supports the standard loop variants: <code>for</code>, <code>while</code>, <code>do ... while</code> etc.</p>
<h3>The Gosu <em>for</em> loop</h3>
<p>The <code>for</code> loop in Gosu allows you to iterate over both arrays and anything that implements
the <code>java.lang.Iterable</code> interface.</p>
<pre class="prettyprint eval-gs">
var list = { "one", "two", "three" } // Creates a java.lang.List<String>
for ( num in list ) {
print( num )
}</pre>
<p>You can also get access to the zero-based index of the loop by including an <code>index</code> variable:</p>
<pre class="prettyprint eval-gs">
var list = { "one", "two", "three" }
for ( num in list index i ) {
print ( "${i} : ${num}" ) // i is an int, and num is still of type String
}</pre>
<p>And, if you need access to the iterator for the loop (assuming you are looping over an <code>Iterable</code>)
you can use the <code>iterator</code> keyword:</p>
<pre class="prettyprint eval-gs">
var list = { "one", "two", "three" }
for ( num in list iterator iter ) {
iter.remove()
}
print(list)</pre>
<p>Here are a few examples making use of the Gosu range operator, <code>..</code></p>
<pre class="prettyprint eval">
for ( i in 0..5 ) { // Range from 0 through 5
print ( i ) // Prints 0-5
}
print("---")
// Range from 0 up to 5
for ( i in 0..|5 ) {
print ( i ) // Prints 0-4
}
print("---")
// Range from 1 up to 5
for ( i in 0|..|5 ) {
print ( i ) // Prints 1-4
}
</pre>
<h2>Properties</h2>
<p>Gosu <em>properties</em> are a way to abstract field access in Gosu classes.</p>
<p>Consider this standard Java boilerplate:</p>
<pre class="prettyprint">
public class Foo {
private String _bar = "bar";
public void setBar( String value ) {
_bar = value;
}
public String getBar() {
return _bar;
}
}</pre>
<p>This is a verbose way to simply expose a field, but exposing the field directly has it's own problems, which
is where properties come in.</p>
<p>Here is the same class in Gosu:</p>
<pre class="prettyprint">
public class Foo {
var _bar : String as Bar = "bar" // the 'as Bar' exposes this field as the property Bar
}</pre>
<p>If you want the property to be readonly, you can use the <code>readonly</code> modifier:</p>
<pre class="prettyprint">
public class Foo {
var _bar : String as readonly Bar = "bar"
}</pre>
<p>If you want to add some logic to the get or set of a propery, you can use this longer syntax:</p>
<pre class="prettyprint">
public class Foo {
var _bar = "bar"
property get Bar() : String {
return _bar
}
property set Bar( value : String ) {
if(value == "Foo") throw "That's not a valid value for Bar!"
_bar = value
}
}</pre>
<p>Reading and writing properties works just like accessing a field:</p>
<pre class="prettyprint">
var f = new Foo()
f.Bar = "su"
print( f.Bar )
</pre>
<h2>Null Safety</h2>
<p>Gosu offers a few helpful tricks to deal with <code>null</code> in your code.</p>
<h3>Null Safe Method Invocation</h3>
<p>Consider this code:</p>
<pre class="prettyprint">
var aList = getAListOfStrings()
if(aList.get(0).isEmpty()) {
print("The first string is empty")
}
</pre>
<p>This code can cause a <code>NullPointerException</code> if either the list or the first string in the list
is null. We can address this by using the null-safe invocation operator <code>?.</code>:</p>
<pre class="prettyprint">
var aList = getAListOfStrings()
if(aList?.get(0)?.isEmpty()) {
print("The first string is empty")
}
</pre>
<p>The null safe invocation operator works on both methods and properties.</p>
<h3>The Elvis Operator</h3>
<p>Sometimes you want a default value if an expression is null. For this use case, Gosu supports the Elvis
Operator, <code>?:</code>:</p>
<pre class="prettyprint">
var myString = getAPossiblyNullString() ?: "default"
</pre>
<p>If <code>getAPossiblyNullString</code> returns <code>null</code>, then the value <code>"default"</code> will
be assigned to <code>myString</code></p>
<h2>Classes</h2>
<p>Gosu classes have a familiar syntax. Gosu classes are defined in a file ending with the <code>.gs</code>
extension.</p>
<p>Here is a basic Gosu class:</p>
<pre class="prettyprint">
package example
uses java.util.List
class SampleClass {
var _names : List<String> // a private class var
// A public constructor
construct( names : List<String> ) {
_names = names
}
// A public function
function printNames( prefix : String ) {
for( n in _names ) {
print( prefix + n )
}
}
// A public property getter, making 'Names' a read-only property
property get Names() : List<String> {
return _names
}
}
</pre>
<p>
The above code demonstrates the following features:
</p>
<ul>
<li>The <code>uses</code> statement, which is identical to the <code>import</code> statement in Java, and makes a class (or package of classes) available for use without qualification.</li>
<li>A class variable, declared using the <code>var</code> keyword, just like local variables. Class variables default to private access. You can declare them to be <code>static</code> as well.</li>
<li>A class constructor, declared using the <code>construct</code> keyword. This constructor allows you to declare new instances of<code>SampleClass</code> like so:
<pre class="prettyprint">
var c = new SampleClass({"joe", "john", "jack"})
</pre> NOTE: Constructors default to public access.</li>
<li>A function, declared using the <code>function</code> keyword. This function takes a <code>String</code> argument, and returns no value, so no return type declaration is necessary. It can be invoked like so:
<pre class="prettyprint">
var c = new SampleClass({"joe", "john", "jack"})
c.printNames("* ")
</pre></li>
<li>A property getter, declared using the <code>property</code> and <code>get</code> keywords. This property returns a list of strings. It can be invoked like so:
<pre class="prettyprint">
var c = new SampleClass({"joe", "john", "jack"})
print( c.Names )
</pre></li>
</ul>
<h3>Named Arguments & Default Parameters</h3>
<p>Gosu supports both named arguments and default parameter values, which can dramatically improve APIs.<p>
<p>Let's say you wanted to make the argument to <code>printNames()</code> in the class above optional, with a
default value of <code>"> "</code>. You would change the parameter declaration to:</p>
<pre class="prettyprint">
// A public function
function printNames( prefix : String = "> ") {
for( n in _names ) {
print( prefix + n )
}
}
</pre>
<p>And you could now invoke it like so:</p>
<pre class="prettyprint">
var c = new SampleClass({"joe", "john", "jack"})
c.printNames() // No argument is necessary, it will use the default value of "> "
</pre>
<p>Additionally, Gosu allows you to use a named argument syntax when you are working with non-overloaded methods
on Gosu classes. You prefix the parameter name with a colon <code>:</code> like so:</p>
<pre class="prettyprint">
var c = new SampleClass({"joe", "john", "jack"})
c.printNames(:prefix = "* ")
</pre>
<p>Named arguments can be used to clarify code, so you don't end up with things like this:</p>
<pre class="prettyprint">
someMethod(true, false, null, false, true) //bwah?
someMethod( :enableLogging = true, :debug = false,
:contextObject = null, :trace = false,
:summarizeTiming = true) //Oh, I see
</pre>
<h3>Superclasses, Interfaces and Delegates</h3>
<p>Gosu classes can extend other classes and implement interfaces just like in Java, using the
<code>extends</code> and <code>implements</code> keywords respectively.
</p>
<p>
One interesting additional feature of Gosu is the ability to delegate the implementation of an interface to a
class variable using the <code>delegate</code> and <code>represents</code> keywords:
</p>
<pre class="prettyprint">
uses java.lang.Runnable
class MyRunnable implements Runnable {
//A delegate, exposed as the Impl property
delegate _runnable represents Runnable
property get Impl : Runnable {
return _runnable
}
property set Impl( r : Runnable ) {
_runnable = r
}
}
</pre>
<p>Note that the class <code>MyRunnable</code> does not declare a <code>run()</code> method, as
<code>Runnable</code> requires. Rather, it uses the delegate field <code>_runnable</code> to implement the
interface:</p>
<pre class="prettyprint">
var x = new MyRunnable()
x.Impl = new Runnable() {
function run() {
print("Hello, Delegation")
}
}
x.run() // prints "Hello, Delegation"
</pre>
<p>Delegates give you a convenient way to favor <a
href="http://www.artima.com/lejava/articles/designprinciples4.html">composition over inheritance</a>.</p>
<h2>The Using Statement</h2>
<p>The <code>using</code> statement allows you to wrap sections of code that require connections to be closed to
be handled automatically when the block finishes. Instead of writing code like this:</p>
<pre class="prettyprint">
var conn = getConnection()
try {
conn.execute( "Some advanced SQL" )
} finally {
conn.close()
}
</pre>
<p>In Gosu, you can use the <code>using</code> statement which will handle closing the <code>Connection</code>
for you:</p>
<pre class="prettyprint">
using( var conn = getConnection() ) {
conn.execute( "Some advanced SQL" )
}
</pre>
<p>The <code>using</code> statement works with the following interfaces:</p>
<ul>
<li><code>java.io.Closeable</code></li>
<li><code>java.util.concurrent.locks.Lock</code></li>
<li><code>gw.lang.IReentrant</code></li>
<li><code>gw.lang.IDisposable</code></li>
</ul>
</section>
<!-- Gosu Programs -->
<section id="gsp">
<div class="page-header">
<h1>Gosu Program Files</h1>
</div>
<p>Gosu doesn't have the concept of a <code>public static void main(String[] args)</code> entrypoint. Instead, it
has programs, which are just bits of code in file ending a <code>.gsp</code> extension.</p>
<p>Here is a simple <em>Hello World</em> application, in the file hello.gsp:</p>
<pre class="prettyprint">
print ( "Hello World!" )
</pre>
<p>Running the program is simple:</p>
<pre>
$> gosu hello.gsp
Hello World!
</pre>
<h2>Classpath Statements, Program Extends & Shebang</h2>
<p>Gosu programs can embed a classpath in their source, obviating the need for users to pass in a correct
classpath externally:</p>
<pre class="prettyprint">
#! /path/to/gosu
classpath "../src,../lib/lib1.jar"
print( "Here is a library object: ${new SweetLibraryObject()}")
</pre>
<p>
The classpath statement is comma delimited, to avoid system specific dependencies. Each path on it will be added
to the classpath. If a path points at a folder and that folder contains jars, all those jars will be added to
the classpath as well.
</p>
<p>The classpath can also include Maven coordinates, and Gosu will automatically resolve and download them
at runtime:</p>
<pre class="prettyprint">
#! /path/to/gosu
classpath "../src,org.gosu-lang.gosu:sparkgs:0.1.0"
print( "Here is a library object: ${new SweetLibraryObject()}")
</pre>
<p>Gosu supports the Unix shebang standard, so your program can begin with <code>#! gosu</code> and Unix-like
shells will execute the script with gosu. This makes it much more pleasant to run gosu programs:</p>
<pre>
$> ./my_sweet_gosu_program.gsp
Here is a sweet library object: super.SweetLibraryObject@12b27c3
</pre>
<p>
No wrapping scripts, no complicated class paths.
</p>
<p>Finally, you can set the superclass for a program using the <code>extends</code> keyword:</p>
<pre class="prettyprint">
classpath "org.gosu-lang.gosu:sparkgs:0.1.0"
extends sparkgs.SparkFile // this is a sparkfile program
get('/', \-> "Hello World")
</pre>
<p>This allows you to access methods and features in the parent class within your program, and can be used to
create simple Gosu-based scripting tools.</p>
</section>
<!-- Blocks -->
<a id="blocks"></a>
<section>
<div class="page-header">
<h1>Blocks</h1>
</div>
<p>Blocks (also called closures or lambda expressions) are a simple way to specify an inline function. They have a
lot of uses, but they really shine in data structure manipulation:</p>
<pre class="prettyprint">
var lstOfStrings = {"This", "is", "a", "list"}
var longStrings = lstOfStrings.where( \ s -> s.length > 2 )
print( longStrings.join(", ") ) // prints "This, list"
</pre>
<p>The <code>\ s -> s.length > 2 </code> is the block. It declares an inline function that says "Given a String
<code>s</code> return whether <code>s.length</code> is greater than two".</p>
<p>You can think of it as an inline version of this function:</p>
<pre class="prettyprint">
function isLongerThanTwo( s : String ) : boolean {
return s.length > 2
}
</pre>
<p>Blocks allow you to express your logic much more succinctly.</p>
<p>
Note that the blocks parameter, <code>s</code>, does not have a type annotation. Gosu does type inference here
and figures out that <code>s</code> is a <code>String</code>.</p>
<p>With blocks you can dramatically reduce the amount of code you write when compared with Java.</p>
<p>Consider this complicated Java code:</p>
<pre class="prettyprint">
List<String> lstOfStrings = Arrays.asList("This", "is", "a", "list");
List<String> longStrings = new ArrayList<String>();
for( String s : lstOfStrings ) {
if( s.length() > 2 ) {
longStrings.add( s.toUpperCase() );
}
}
Collections.sort(longStrings, new Comparator<String>() {
public int compare( String s, String s2 ) {
return s.compareTo( s2 );
}
})
StringBuilder sb = new StringBuilder();
for( String s : longStrings ) {
if(sb.length() != 0) {
sb.append(", ");
}
sb.append(s);
}
System.out.println(sb.toString());
</pre>
<p>This can be rewritten in Gosu as:</p>
<pre class="prettyprint">
var lstOfStrings = {"This", "is", "a", "list"}
var longStrings = lstOfStrings.where( \ s -> s.length > 2 )
.map( \ s -> s.toUpperCase() ) // converts each string to upper case
.orderBy( \ s -> s ) // there is a .order() method that could be used here instead
print( longStrings.join(", ") ) // prints "LIST, THIS"
</pre>
<p>
The Gosu code is clearer and far more brief.
</p>
<h4>Blocks and Interfaces</h4>
<p>
Java has many interfaces that contain a single method, which are used as a stand-in for actual closures. In
order to facilitate Java interoperability, Gosu blocks and one-method interfaces are automatically converted
between one another:
</p>
<pre class="prettyprint">
var r : Runnable
r = \-> print("This block was converted to a Runnable")
</pre>
<p>
This makes some Java APIs much more pleasant to work with in Gosu.
</p>
</section>
<!-- Enhancements -->
<section id="enhancements">
<div class="page-header">
<h1>Enhancements</h1>
</div>
<p>Enhancements provide a way to add methods and properties to existing types. They are similar to
<a href="http://msdn.microsoft.com/en-us/library/bb383977.aspx">Extension Methods</a> in C#, but do not need to
be explicitly imported.</p>
<p>Enhancements are defined in files ending with a .gsx suffix and cannot be defined inline
with other Gosu resources. Here is an example enhancement for the type <code>java.lang.String</code></p>
<pre class="prettyprint">
package example
enhancement MyStringEnhancement : String {
function printWarning() {
print ( "WARNING: " + this );
}
}
</pre>
<p>In enhancements, the <code>this</code> symbol refers to the <em>enhanced type</em>, as opposed to the
enhancement itself.</p>
<p>Once an enhancement has been added to your classpath, you can use it in any place you have an object of the
enhanced type with no need to explicitly import the enhancement itself. Therefore, using the enhancement above
is as simple as just calling the new function anywhere you have a String:</p>
<pre class="prettyprint">
"I'm not sure I can go back to Java".printWarning()
</pre>
<h2>Semantics And Limitations</h2>
<p>The above code can be thought of as shorthand for this code:</p>
<pre class="prettyprint">
example.MyStringEnhancement.print( "Warning: " + "Hello World" )
</pre>
<p>Enhancements are <em>statically</em> dispatched. This means they cannot be used to implement interfaces or to
achieve polymorphism</p>
<h2>Generics</h2>
<p>Enhancements can be generic, so you can add an enhancement to <code>List<T></code>:</p>
<pre class="prettyprint">
package example
uses java.util.List
enhancement MyListEnhancement<T> : List<T> {
function firstAndLast() : List<T> {
return {this.first(), this.last()}
}
}
</pre>
<p>This method will now be available on all generic lists, and will be properly typed.</p>
<h3>Type Variable Reification</h3>
<p>
Unlike in Java, type variables <em>can</em> be used in general expressions in Gosu. In Enhancements, the type
variables are statically, rather than dynamically, reified, much like enhancement methods are statically, rather
than dynamically dispatched. The enhancement method <code>toTypedArray():T[]</code> on
<code>Iterable<T></code> demonstrates this:
</p>
<pre class="prettyprint">
var lstOfStrings : List<String> = {"a", "b", "c"}
var arrOfStrings = lstOfStrings.toTypedArray() //returns a String[]
var lstOfObjs : List<Object> = lstOfStrings //type variables are covariant in Gosu, see <a href="generics.html">generics</a>
var arrOfObjs = lstOfObjs.toTypedArray() //returns an Object[]
</pre>
<p>
This "best effort" reification usually does what you want, but can occasionally lead to surprising results.
</p>
<h3>Enhancing Parameterized Types</h3>
<p>A really neat trick with enhancements is that you can enhance <em>parameterized</em> types:</p>
<pre class="prettyprint">
package example
uses java.util.*
enhancement MyListOfDatesEnhancement : List<Date> {
function allBetween( start : Date, end : Date ) : List<Date>{
this.where( \ d -> start <= d and d <= end )
}
}
</pre>
<p>
This is how all lists of comparable objects have the <code>sort()</code> method on them, while other lists do
not.
</p>
</section>
<!-- Strings -->
<section id="strings">
<div class="page-header">
<h1>Strings & Gosu Templates</h1>
</div>
<p>String literals in Gosu can be expressed using either double or single quotes:</p>
<pre class="prettyprint">
var s1 = "I'm a String"
var s2 = 'I\'m also a String!'
</pre>
<p>Strings support concatenation:</p>
<pre class="prettyprint">
var s1 = "Hello"
var s2 = "World!"
print ( s1 + " " + s2 ) // prints "Hello World!"
</pre>
<p>Strings also support inline expressions using the <code>${}</code> syntax:</p>
<pre class="prettyprint">
var s1 = "Hello"
var s2 = "World!"
print ( "${s1} ${s2}" ) // prints "Hello World!"
</pre>
<p>Because Strings are so common, there are also a bunch of handy <em>enhancements</em> which allows for easy
conversion from strings to other types:</p>
<pre class="prettyprint">
var bool = "true".toBoolean()
var integ = "42".toInt()
var dubble = "42.2".toDouble()
var date = "01/25/2012".toDate()
</pre>
<p>Here is a short sample of additional enhancements on <code>String</code>:</p>
<ul>
<li><code>repeat(n:int)</code> - Repeat the String <code>n</code> times</li>
<li><code>chomp()</code> - Removes a trailing newline from the end of the String, if present</li>
<li><code>chop()</code> - Remove the last character from the String</li>
<li><code>elide(len:int)</code> - Cap the String at a fixed length and replace the last three characters with '...' to denote truncation</li>
<li><code>rightPad(w:int)</code>, <code>leftPad(w:int)</code>, <code>center(w:int)</code> - Format the string with additional whitespace</li>
<li><code>notBlank()</code> - Returns true if the string is not null and contains at least one non-whitespace character
</ul>
<h2>Gosu Template Files (.gst)</h2>
<p>Gosu supports string templates as first class citizens in the language. A Gosu String Template is a file that
ends in the <code>.gst</code> extension.</p>
<p>Here is an example definition, <code>sample.SampleTemplate.gst</code>:
<pre class="prettyprint">
<%@ params( names : String[] ) %>
All Names: <% for( name in names ) { %>
* ${name}
<% } %>
</pre>
<p>The template explicitly declares the names and types of its arguments using the <code>params()</code> directive</p>
<p>You can render a template by calling the <code>render(w:Writer)</code> or <code>renderToString()</code> static methods:</p>
<p>For each parameter defined in the <code>params</code> directive, an additional argument with that name and
type is added to the <code>render()</code> and <code>renderToString()</code> methods.</p>
<p>So, given the template definition above, you could render it like so:</p>
<pre class="prettyprint">
// render directly to string
var str = sample.SampleTemplate.renderToString( {"Joe", "John", "Josh"} )
print( str)
// render directly to writer (potentially more efficient for large strings)
var writer = new java.io.StringWriter()
sample.SampleTemplate.render(writer, {"Joe", "John", "Josh"})
print( writer )
</pre>
<p>Using templates gives you a type safe way to generate large strings in your applications.</p>
</section>
<!-- Collections -->
<section id="collections">
<div class="page-header">
<h1>Collections In Gosu</h1>
</div>
<h2>List & Map Syntax</h2>
<p><code>java.util.List</code> and <code>java.util.Map</code> are the two most commonly used
data structures in Java. Unfortunately, they can also be fairly verbose to deal with in Java:</p>
<pre class="prettyprint">
Map<String, Object> map = new HashMap<String, Object>();
map.put( "isOverlyVerbose", true );
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
list.add( map );
</pre>
<p>Luckily Gosu provides a shorthand syntax for these two types, allowing the above code to simply be written
as:</p>
<pre class="prettyprint">
var map = { "isOverlyVerbose" -> false }
var list = { map }
</pre>
<h2>Enhancements</h2>
<p>Gosu adds a whole slew of enhancements to collections classes. Here are some of the most useful ones for
<code>java.lang.Iterable<T></code>:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Enhancement</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="function">allMatch( cond(elt1 : T):boolean ) : boolean
</td>
<td>Returns true if all elements in this collection match the given condition and false otherwise
</td>
</tr>
<tr>
<td class="function">average( select:block(elt:T):java.lang.Number ) : BigDecimal
</td>
<td>Return the average of the mapped value</td>
</tr>
<tr>
<td class="function">concat( that : Collection<T> ) : Collection<T>
</td>
<td>Return a new list that is the concatenation of the two lists</td>
</tr>
<tr>
<td class="function">Count() : int
</td>
<td>Return the number of elements in this Iterable object</td>
</tr>
<tr>
<td class="function">countWhere( cond(elt:T):boolean ) : int
</td>
<td>Return the count of elements in this collection that match the given condition</td>
</tr>
<tr>
<td class="function">disjunction( that : Collection<T> ) : Set<T>
</td>
<td>Returns a the set disjunction of this collection and the other collection, that is, all elements
that are in one collection <em>not</em> and not the other
</td>
</tr>
<tr>
<td class="function">each( operation(elt : T) )
</td>
<td>This method will invoke the operation on each element in the Collection</td>
</tr>
<tr>
<td class="function">eachWithIndex( operation(elt : T, index : int ) )
</td>
<td>This method will invoke the operation on each element in the Collection, passing in the index as
well as the element
</td>
</tr>
<tr>
<td class="function">first() : T
</td>
<td>Returns the first element in this collection. If the collection is empty, null is returned</td>
</tr>
<tr>
<td class="function">firstWhere( cond(elt:T):boolean ) : T
</td>
<td>Returns the first element in this collection that matches the given condition.
If no element matches the criteria, null is returned
</td>
</tr>
<tr>
<td class="function">fold( aggregator(elt1 : T, elt2 : T):T ) : T
</td>
<td>Returns all the values of this collection folded into a single value</td>
</tr>
<tr>
<td class="function">hasMatch( cond(elt1 : T):boolean ) : boolean
</td>
<td>Returns true if any elements in this collection match the given condition and false otherwise
</td>
</tr>
<tr>
<td class="function">intersect( that : Collection<T> ) : Set<T>
</td>
<td>Return the set intersection of these two collections</td>
</tr>
<tr>
<td class="function">join( delimiter : String ) : String
</td>
<td>Coerces each element in the collecion to a string and joins them together with the
given delimiter
</td>
</tr>
<tr>
<td class="function">last() : T
</td>
<td>Returns the last element in this collection. If the collection is empty, null is returned</td>
</tr>
<tr>
<td class="function">lastWhere( cond(elt:T):boolean ) : T
</td>
<td>Returns the last element in this collection that matches the given condition.
If the collection is empty, null is returned
</td>
</tr>
<tr>
<td class="function">map<Q>( mapper(elt : T):Q ) : List<Q>
</td>
<td>Maps the values of the collection to a list of values by calling the
mapper block on each element
</td>
</tr>
<tr>
<td class="function">maxBy( comparison(elt : T):Comparable ) : T
</td>
<td>Returns the maximum value of this collection with respect to the Comparable attribute calculated
by the given block. If more than one element has the maximum value, the first element encountered is
returned
</td>
</tr>
<tr>
<td class="function">max<R extends Comparable>( transform(elt:T):R ) : R
</td>
<td>Returns the maximum value of the transformed elements</td>
</tr>
<tr>
<td class="function">minBy( comparison(elt : T):Comparable ) : T
</td>
<td>Returns the minimum value of this collection with respect to the Comparable attribute calculated
by the given block. If more than one element has the minimum value, the first element encountered is
returned
</td>
</tr>
<tr>
<td class="function">min<R extends Comparable>( transform(elt:T):R ) : R
</td>
<td>Returns the minimum value of the transformed elements</td>
</tr>
<tr>
<td class="function">partitionUniquely<Q>( mapper(elt : T):Q ) : Map<Q, T>
</td>
<td>Partitions each element into a Map where the keys are the value produce by the mapper block and
the values are the elements of the Collection. If two elements map to the same key an
IllegalStateException is thrown
</td>
</tr>
<tr>
<td class="function">orderBy<R extends Comparable>( value(elt:T):R ) : IOrderedList<T>
</td>
<td>Returns a lazily-computed List that consists of the elements of this Collection, ordered by the
value mapped to by the given block
</td>
</tr>
<tr>
<td class="function">orderByDescending<R extends Comparable>( value(elt:T):R ) : IOrderedList<T>
</td>
<td>Returns a lazily-computed List that consists of the elements of this Collection, descendingly
ordered by the value mapped to by the given block
</td>
</tr>
<tr>
<td class="function">reduce<V>( init : V, aggregator(val : V, elt2 : T):V ) : V
</td>
<td>Returns all the values of this collection down to a single value</td>
</tr>
<tr>
<td class="function">removeWhere( cond(elt:T):boolean )
</td>
<td>Removes all elements that match the given condition in this collection</td>
</tr>
<tr>
<td class="function">retainWhere( cond(elt:T):boolean )
</td>
<td>Retains all elements that match the given condition in this collection</td>
</tr>
<tr>
<td class="function">reverse() : List<T>
</td>
<td>Returns a new list of the elements in the collection, in their reverse iteration order</td>
</tr>
<tr>
<td class="function">single() : T
</td>
<td>Returns a single element from this iterable, if only one exists. It no elements are in this
iterable, or if there are more than one elements in it, an IllegalStateException is thrown
</td>
</tr>
<tr>
<td class="function">singleWhere( cond(elt:T):boolean ) : T
</td>
<td>Returns a single item matching the given condition. If there is no such element or if multiple
elements match the condition, and IllegalStateException is thrown
</td>
</tr>
<tr>
<td class="function">subtract( that : Collection<T> ) : Set<T>
</td>
<td>Returns the Set subtraction of that Collection from this Collection</td>
</tr>
<tr>
<td class="function">toCollection() : Collection<T>
</td>
<td>If this Iterable is already a Collection, return this Itearble cast to a Collection.
Otherwise create a new Collection and copy this Iterable into it
</td>
</tr>
<tr>
<td class="function">toList() : List<T>
</td>
<td>If this Iterable is already a List, return this Iterable cast to a List.
Otherwise create a new List and copy this Iterable into it
</td>
</tr>
<tr>
<td class="function">toSet() : Set<T>
</td>
<td>If this Iterable is already a Set, return this Iterable cast to a Set. Otherwise create a new