├── source
├── de
│ ├── package.ceylon
│ ├── module.ceylon
│ ├── 07benannte_argumente.ceylon
│ ├── 06schnittstellen_operatoren.ceylon
│ ├── 02klassen.ceylon
│ ├── 05aufzählungen_folgen.ceylon
│ ├── 01grundlagen.ceylon
│ ├── 03null_vereinigung_schnitt.ceylon
│ └── 04funktionen.ceylon
├── en
│ ├── module.ceylon
│ ├── package.ceylon
│ ├── 06interfaces_operators.ceylon
│ ├── 07namedarguments.ceylon
│ ├── 02classes.ceylon
│ ├── 05iterables_sequences.ceylon
│ ├── 03null_unions_intersections.ceylon
│ ├── 01basics.ceylon
│ └── 04functions.ceylon
├── es
│ ├── module.ceylon
│ ├── package.ceylon
│ ├── 06interfaces_operadores.ceylon
│ ├── 07argumentos_con_nombre.ceylon
│ ├── 01bases.ceylon
│ ├── 02clases.ceylon
│ ├── 05iterables_secuencias.ceylon
│ ├── 03null_union_interseccion.ceylon
│ └── 04funciones.ceylon
└── fr
│ ├── module.ceylon
│ ├── package.ceylon
│ ├── 06interfaces_operateurs.ceylon
│ ├── 07arguments_nommes.ceylon
│ ├── 02classes.ceylon
│ ├── 05iterables_sequences.ceylon
│ ├── 01bases.ceylon
│ └── 03null_unions_intersections.ceylon
├── .ceylon
├── ide-config
├── bootstrap
│ ├── ceylon-bootstrap.jar
│ └── ceylon-bootstrap.properties
└── config
├── .idea
├── copyright
│ └── profiles_settings.xml
├── vcs.xml
├── modules.xml
├── compiler.xml
└── misc.xml
├── .gitignore
├── .settings
└── org.eclipse.core.resources.prefs
├── README.md
├── .classpath
├── .project
├── ceylon-walkthrough.iml
├── ceylonb
└── ceylonb.bat
/source/de/package.ceylon:
--------------------------------------------------------------------------------
1 | "Die Ceylon-Demo auf Deutsch."
2 | shared package de;
3 |
--------------------------------------------------------------------------------
/source/en/module.ceylon:
--------------------------------------------------------------------------------
1 | module en "1" {
2 | import ceylon.collection "1.3.3";
3 | }
--------------------------------------------------------------------------------
/source/en/package.ceylon:
--------------------------------------------------------------------------------
1 | "The Ceylon walkthrough in English."
2 | shared package en;
3 |
--------------------------------------------------------------------------------
/source/es/module.ceylon:
--------------------------------------------------------------------------------
1 | module es "1" {
2 | import ceylon.collection "1.3.3";
3 | }
--------------------------------------------------------------------------------
/source/es/package.ceylon:
--------------------------------------------------------------------------------
1 | "El recorrido de Ceylon en español."
2 | shared package es;
3 |
--------------------------------------------------------------------------------
/source/de/module.ceylon:
--------------------------------------------------------------------------------
1 | module de "1.0.0" {
2 | import ceylon.collection "1.3.3";
3 | }
--------------------------------------------------------------------------------
/source/fr/module.ceylon:
--------------------------------------------------------------------------------
1 | module fr "1.0.0" {
2 | import ceylon.collection "1.3.3";
3 | }
--------------------------------------------------------------------------------
/source/fr/package.ceylon:
--------------------------------------------------------------------------------
1 | "Visite guidée de Ceylon en français"
2 | shared package fr;
3 |
--------------------------------------------------------------------------------
/.ceylon/ide-config:
--------------------------------------------------------------------------------
1 |
2 | [project]
3 | compile-jvm=true
4 | compile-js=false
5 | system-repository=
6 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.ceylon/bootstrap/ceylon-bootstrap.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceylon/ceylon-walkthrough/HEAD/.ceylon/bootstrap/ceylon-bootstrap.jar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /classes
2 | /modules
3 |
4 | /.exploded/
5 |
6 | /.idea/libraries
7 | /.idea/workspace.xml
8 |
9 | *~
10 | \#*
11 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding//source/es/package.ceylon=UTF-8
3 | encoding/=UTF-8
4 |
--------------------------------------------------------------------------------
/.ceylon/bootstrap/ceylon-bootstrap.properties:
--------------------------------------------------------------------------------
1 | #Generated by 'ceylon bootstrap'
2 | #Thu Mar 16 09:27:33 PDT 2017
3 | distribution=https\://ceylon-lang.org/download/dist/1_3_2
4 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.ceylon/config:
--------------------------------------------------------------------------------
1 |
2 | [defaults]
3 | encoding=UTF-8
4 | offline=false
5 | flatclasspath=false
6 | autoexportmavendependencies=false
7 | fullyexportmavendependencies=false
8 |
9 | [compiler]
10 | suppresswarning=filenameNonAscii
11 | suppresswarning=deprecation
12 | suppresswarning=unusedDeclaration
13 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Ceylon Walkthrough
2 | ==================
3 |
4 | An IDE-based walkthrough of the whole language. Check out this
5 | project in Eclipse or IntelliJ to get started. You must install
6 | Ceylon IDE first.
7 |
8 | Instructions on getting started are available at
9 | .
10 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | ceylon-walkthrough
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | com.redhat.ceylon.eclipse.ui.ceylonBuilder
15 |
16 |
17 | explodeModules
18 | true
19 |
20 |
21 | systemRepo
22 |
23 |
24 |
25 |
26 |
27 |
28 | com.redhat.ceylon.eclipse.ui.ceylonNature
29 | org.eclipse.jdt.core.javanature
30 |
31 |
32 |
--------------------------------------------------------------------------------
/ceylon-walkthrough.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Do not edit, modify .config/ide-config instead
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/ceylonb:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # resolve links - $0 may be a softlink
4 | PRG="$0"
5 | while [ -h "$PRG" ]; do
6 | ls="$(ls -ld "$PRG")"
7 | link="${ls##*-> }" # remove largest prefix: yields link target (behind ->)
8 | if [ "$link" != "${link#/}" ]; then # remove prefix / if present
9 | # path was absolute
10 | PRG="$link"
11 | else
12 | # was not
13 | PRG="$(dirname "$PRG")/$link"
14 | fi
15 | done
16 |
17 | DIR="$(dirname "$PRG")"
18 |
19 | # Check if we should use a distribution bootstrap
20 | if [ -f "$DIR/.ceylon/bootstrap/ceylon-bootstrap.properties" ] && [ -f "$DIR/.ceylon/bootstrap/ceylon-bootstrap.jar" ]; then
21 | # Using bootstrap
22 | LIB="$DIR/.ceylon/bootstrap"
23 | else
24 | # Normal execution
25 | CEYLON_HOME="$DIR/.."
26 | LIB="$CEYLON_HOME/lib"
27 |
28 | if [ "$1" = "--show-home" ]; then
29 | echo "$CEYLON_HOME"
30 | exit
31 | fi
32 | fi
33 |
34 | if [ -z "$JAVA_HOME" ]; then
35 | JAVA="java"
36 | else
37 | JAVA="$JAVA_HOME/bin/java"
38 | fi
39 |
40 | # Make sure we have java installed
41 | if ! hash java 2>&-
42 | then
43 | echo >&2 "Java not found, you must install Java in order to compile and run Ceylon programs"
44 | echo >&2 "Go to http://www.java.com/getjava/ to download the latest version of Java"
45 | exit 1
46 | fi
47 |
48 | #JAVA_DEBUG_OPTS="-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y"
49 |
50 | if [ "$PRESERVE_JAVA_OPTS" != "true" ]; then
51 | PREPEND_JAVA_OPTS="$JAVA_DEBUG_OPTS"
52 | if [ -n "$COLUMNS" ]; then
53 | CEYL_COLS="$COLUMNS"
54 | elif stty size 2>/dev/null >/dev/null; then
55 | CEYL_COLS="$(stty size 2>/dev/null | cut -d' ' -f2)"
56 | else
57 | CEYL_COLS="$(tput 2>/dev/null cols)"
58 | fi
59 | PREPEND_JAVA_OPTS="$PREPEND_JAVA_OPTS -Dcom.redhat.ceylon.common.tool.terminal.width=$CEYL_COLS"
60 | PREPEND_JAVA_OPTS="$PREPEND_JAVA_OPTS -Dcom.redhat.ceylon.common.tool.progname=$(basename "$PRG")"
61 | fi
62 | for arg; do
63 | case $arg in
64 | --java=*) JAVA_OPTS="$JAVA_OPTS ${arg#--java=}";;
65 | [!-]*) break;;
66 | esac
67 | done
68 | JAVA_OPTS="$PREPEND_JAVA_OPTS $JAVA_OPTS"
69 |
70 | BOOTSTRAP="$LIB/ceylon-bootstrap.jar"
71 |
72 | # Check for cygwin, convert bootstrap path to Windows format
73 | case "`uname`" in
74 | CYGWIN*) [ -n "$LIB" ] && BOOTSTRAP=`cygpath -w "$BOOTSTRAP"`
75 | esac
76 |
77 | exec "$JAVA" \
78 | $JAVA_OPTS \
79 | -jar "$BOOTSTRAP" \
80 | "$@"
81 |
82 |
--------------------------------------------------------------------------------
/ceylonb.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal ENABLEDELAYEDEXPANSION
3 |
4 | :: Check if we should use a distribution bootstrap
5 | pushd "%~dp0"
6 | set "DIR=%CD%"
7 | popd
8 | if NOT exist "%DIR%\.ceylon\bootstrap\ceylon-bootstrap.properties" (
9 | goto :normal
10 | )
11 | if NOT exist "%DIR%\.ceylon\bootstrap\ceylon-bootstrap.jar" (
12 | goto :normal
13 | )
14 |
15 | :: Using bootstrap
16 | set "LIB=%DIR%\.ceylon\bootstrap"
17 |
18 | goto :endbs
19 |
20 | :normal
21 |
22 | :: Normal execution
23 |
24 | :: Find CEYLON_HOME
25 | pushd "%~dp0.."
26 | set "CEYLON_HOME=%CD%"
27 | popd
28 | set "LIB=%CEYLON_HOME%\lib"
29 |
30 | if "%~1" == "--show-home" (
31 | @echo %CEYLON_HOME%
32 | exit /b 1
33 | )
34 |
35 | :endbs
36 |
37 | :: Find Java
38 |
39 | :: Only check the registry if JAVA_HOME is not already set
40 | IF NOT "%JAVA_HOME%" == "" (
41 | goto :javaend
42 | )
43 |
44 | :: Find Java in the registry
45 | set "KEY_NAME=HKLM\SOFTWARE\JavaSoft\Java Runtime Environment"
46 | set "KEY_NAME2=HKLM\SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment"
47 |
48 | :: get the current version
49 | FOR /F "usebackq skip=2 tokens=3" %%A IN (`REG QUERY "%KEY_NAME%" /v CurrentVersion 2^>nul`) DO (
50 | set "ValueValue=%%A"
51 | )
52 |
53 | if "%ValueValue%" NEQ "" (
54 | set "JAVA_CURRENT=%KEY_NAME%\%ValueValue%"
55 | ) else (
56 | rem Try again for 64bit systems
57 |
58 | FOR /F "usebackq skip=2 tokens=3" %%A IN (`REG QUERY "%KEY_NAME2%" /v CurrentVersion 2^>nul`) DO (
59 | set "JAVA_CURRENT=%KEY_NAME2%\%%A"
60 | )
61 | )
62 |
63 | if "%ValueValue%" NEQ "" (
64 | set "JAVA_CURRENT=%KEY_NAME%\%ValueValue%"
65 | ) else (
66 | rem Try again for 64bit systems from a 32-bit process
67 |
68 | FOR /F "usebackq skip=2 tokens=3" %%A IN (`REG QUERY "%KEY_NAME%" /v CurrentVersion /reg:64 2^>nul`) DO (
69 | set "JAVA_CURRENT=%KEY_NAME%\%%A"
70 | )
71 | )
72 |
73 | if "%JAVA_CURRENT%" == "" (
74 | @echo Java not found, you must install Java in order to compile and run Ceylon programs
75 | @echo Go to http://www.java.com/getjava/ to download the latest version of Java
76 | exit /b 1
77 | )
78 |
79 | :: get the javahome
80 | FOR /F "usebackq skip=2 tokens=3*" %%A IN (`REG QUERY "%JAVA_CURRENT%" /v JavaHome 2^>nul`) DO (
81 | set "JAVA_HOME=%%A %%B"
82 | )
83 |
84 | if "%JAVA_HOME%" EQU "" (
85 | rem Try again for 64bit systems from a 32-bit process
86 | FOR /F "usebackq skip=2 tokens=3*" %%A IN (`REG QUERY "%JAVA_CURRENT%" /v JavaHome /reg:64 2^>nul`) DO (
87 | set "JAVA_HOME=%%A %%B"
88 | )
89 | )
90 |
91 | :javaend
92 |
93 | set "JAVA=%JAVA_HOME%\bin\java.exe"
94 |
95 | :: Check that Java executable actually exists
96 | if not exist "%JAVA%" (
97 | @echo "Cannot find java.exe at %JAVA%, check that your JAVA_HOME variable is pointing to the right place"
98 | exit /b 1
99 | )
100 |
101 | rem set JAVA_DEBUG_OPTS="-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y"
102 |
103 | if NOT "%PRESERVE_JAVA_OPTS%" == "true" (
104 | set PREPEND_JAVA_OPTS=%JAVA_DEBUG_OPTS%
105 | rem Other java opts go here
106 | )
107 |
108 | rem Find any --java options and add their values to JAVA_OPTS
109 | for %%x in (%*) do (
110 | set ARG=%%~x
111 | if "!ARG:~0,7!" EQU "--java=" (
112 | set OPT=!ARG:~7!
113 | set "JAVA_OPTS=!JAVA_OPTS! !OPT!"
114 | ) else if "!ARG!" EQU "--java" (
115 | @echo Error: use --java options with an equal sign and quotes, eg: "--java=-Xmx500m"
116 | exit /b 1
117 | ) else if "!ARG:~0,1!" NEQ "-" (
118 | goto :breakloop
119 | )
120 | )
121 | :breakloop
122 |
123 | set "JAVA_OPTS=%PREPEND_JAVA_OPTS% %JAVA_OPTS%"
124 |
125 | "%JAVA%" ^
126 | %JAVA_OPTS% ^
127 | -jar "%LIB%\ceylon-bootstrap.jar" ^
128 | %*
129 |
130 | endlocal
131 |
132 | if %errorlevel% neq 0 exit /B %errorlevel%
133 |
--------------------------------------------------------------------------------
/source/en/06interfaces_operators.ceylon:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | An interface defines a contract that can be
4 | satisfied by a class. Interfaces may have formal
5 | members, or even concrete members:
6 |
7 | - methods,
8 | - getters and setters, and
9 | - member classes.
10 |
11 | But an interface may not:
12 |
13 | - have an attribute that holds a reference to a
14 | value, or
15 | - define initialization logic.
16 |
17 | Thus, we say that interfaces are stateless. This
18 | means that "diamond" inheritance is unproblematic
19 | in Ceylon.
20 |
21 | */
22 |
23 | interface Writer {
24 |
25 | shared formal void write(String string);
26 |
27 | shared void writeLine(String string) {
28 | write(string + operatingSystem.newline);
29 | }
30 |
31 | }
32 |
33 | /*
34 |
35 | A class may satisfy the interface, inheriting its
36 | members.
37 |
38 | */
39 |
40 | class FunctionWriter(void fun(String string))
41 | satisfies Writer {
42 | write = fun;
43 | }
44 |
45 | shared void testFunctionWriter() {
46 | FunctionWriter(process.write).writeLine("Hello!");
47 | FunctionWriter(process.writeError).writeLine("Ooops!");
48 | }
49 |
50 | /*
51 |
52 | A class may satisfy multiple interfaces. We
53 | use the & symbol to separate the supertypes
54 | because they conceptually form an intersection
55 | of types.
56 |
57 | */
58 |
59 | class TextWriter(StringBuilder stringBuilder)
60 | satisfies Writer & Category<> {
61 |
62 | contains(Object element)
63 | => element in stringBuilder.string;
64 |
65 | write(String string)
66 | => stringBuilder.append(string);
67 |
68 | }
69 |
70 | shared void testTextWriter() {
71 |
72 | value textWriter = TextWriter(StringBuilder());
73 | textWriter.writeLine("Hello :-)");
74 | textWriter.writeLine("Goodbye :-(");
75 |
76 | // "x in category" means "category.contains(x)"
77 | // where category is an instance of Category
78 | assert(":-)" in textWriter);
79 |
80 | }
81 |
82 | /*
83 |
84 | It's especially common to have anonymous classes
85 | that satisfy an interface.
86 |
87 | */
88 |
89 | object consoleWriter satisfies Writer {
90 | write = process.write;
91 | }
92 |
93 | shared void testConsoleWriter() {
94 | consoleWriter.writeLine("Hello!");
95 | consoleWriter.writeLine("Bye!");
96 | }
97 |
98 | /*
99 |
100 | The above anonymous class is a singleton, because
101 | it occurs as a toplevel declaration. But not
102 | every anonymous class is a singleton.
103 |
104 | */
105 |
106 | //this anonymous class is a singleton
107 | object naturals
108 | satisfies Iterable {
109 |
110 | shared actual Iterator iterator() {
111 | //a new instance of this anonymous class
112 | //is created each time iterator() is
113 | //called
114 | object iterator
115 | satisfies Iterator {
116 | variable value int = 1;
117 | next() => int++;
118 | }
119 | return iterator;
120 | }
121 |
122 | }
123 |
124 | /*
125 |
126 | The anonymous class above satisfies Iterable.
127 | That means we can iterate it with a for loop.
128 |
129 | */
130 |
131 | shared void loop() {
132 | for (n in naturals) {
133 | print(n);
134 | }
135 | }
136 |
137 | /*
138 |
139 | Many of the "built-in" language constructs are
140 | defined in terms of interfaces that your own
141 | classes may implement. In particular, most of the
142 | operators are defined in terms of interfaces.
143 |
144 | Let's see how we can define a complex number type
145 | that works just like the built-in numeric types.
146 |
147 | */
148 |
149 | "A complex number class demonstrating operator
150 | polymorphism in Ceylon."
151 | class Complex(shared Float re, shared Float im=0.0)
152 | satisfies Exponentiable {
153 |
154 | negated => Complex(-re,-im);
155 |
156 | plus(Complex other) => Complex(re+other.re, im+other.im);
157 |
158 | minus(Complex other) => Complex(re-other.re, im-other.im);
159 |
160 | times(Complex other) =>
161 | Complex(re*other.re-im*other.im,
162 | re*other.im+im*other.re);
163 |
164 | shared actual Complex divided(Complex other) {
165 | Float d = other.re^2 + other.im^2;
166 | return Complex((re*other.re+im*other.im)/d,
167 | (im*other.re-re*other.im)/d);
168 | }
169 |
170 | "Accepts non-negative powers."
171 | shared actual Complex power(Integer other) {
172 | "exponent must be non-negative"
173 | assert(other>=0);
174 | //lame impl
175 | variable Complex result = Complex(1.0, 0.0);
176 | for (i in 0:other) {
177 | result*=this;
178 | }
179 | return result;
180 | }
181 |
182 | string => im<0.0 then "``re``-``-im``i"
183 | else "``re``+``im``i";
184 |
185 | hash => re.hash + im.hash;
186 |
187 | shared actual Boolean equals(Object that) {
188 | if (is Complex that) {
189 | return re==that.re && im==that.im;
190 | }
191 | else {
192 | return false;
193 | }
194 | }
195 |
196 | }
197 |
198 | Complex i = Complex(0.0, 1.0);
199 |
200 | shared void testComplex() {
201 |
202 | Complex one = Complex(1.0);
203 | Complex zero = Complex(0.0);
204 |
205 | Complex sum = one+i+zero;
206 | assert (sum==Complex(1.0, 1.0));
207 |
208 | Complex zeroProduct = one*zero;
209 | assert (zeroProduct==zero);
210 |
211 | Complex nonzeroProduct = one*i;
212 | assert (nonzeroProduct==i);
213 |
214 | Complex diff = -one-zero-i;
215 | assert (diff==Complex(-1.0, -1.0));
216 |
217 | Complex power = i^3;
218 | assert (power==Complex(-0.0, -1.0));
219 |
220 | Complex quot = one/i;
221 | assert(quot==-i);
222 |
223 | }
224 |
225 | /*
226 |
227 | EXERCISE
228 |
229 | Write a Vector class, that supports vector
230 | addition with + (via the Summable interface) and
231 | scalar multiplication with ** (via the Scalable
232 | interface).
233 |
234 | */
--------------------------------------------------------------------------------
/source/en/07namedarguments.ceylon:
--------------------------------------------------------------------------------
1 | import ceylon.collection {
2 | HashSet,
3 | HashMap
4 | }
5 | /*
6 |
7 | When a function has many parameters, it's
8 | better to list its arguments by name. Named
9 | argument lists are enclosed in braces, and
10 | individual arguments are separated by
11 | semicolons.
12 |
13 | */
14 |
15 | shared void namedArgLists() {
16 | value entry1 = Entry { key = 1; item = "once"; };
17 | value entry2 = Entry { item = "twice"; key = 2; };
18 | value int1 = Integer.parse { string = "1000101"; radix = 2; };
19 | value int2 = Integer.parse { radix = 16; string = "1000101"; };
20 | print(entry1);
21 | print(entry2);
22 | print(int1);
23 | print(int2);
24 | }
25 |
26 | /*
27 |
28 | Even within a named argument list, we're
29 | allowed to list the first arguments
30 | positionally. (The reason for this will
31 | become clear below.)
32 |
33 | */
34 |
35 | shared void namedArgListsWithPositionalArgs() {
36 | Entry { 1; item = "once"; };
37 | Entry { 2; "twice"; };
38 | Integer.parse { "1000101"; radix = 2; };
39 | Integer.parse { "1000101"; 16; };
40 | }
41 |
42 | /*
43 |
44 | At the end of a named argument list, we may
45 | list additional arguments, separated by
46 | commas, which are interpreted as arguments
47 | to the first parameter of type Iterable
48 | which does not already have an argument.
49 |
50 | This is the usual syntax we use for
51 | instantiating container types with an
52 | initially fixed list of elements.
53 |
54 | */
55 |
56 | shared void namedArgListsWithIterableArgs() {
57 | value hello = String { 'H', 'e', 'l', 'l', 'o' };
58 | value immutableSet = set { "once", "twice", "thrice" };
59 | value hashSet = HashSet { 0, 1, -1 };
60 | value hashMap = HashMap { 1->"once", 2->"twice", 3->"thrice", 0->"never" };
61 | print(hello);
62 | print(immutableSet);
63 | print(hashSet);
64 | print(hashMap);
65 | }
66 |
67 | /*
68 |
69 | In Ceylon, anywhere we can write an
70 | arbitrary-length list of values, we can also
71 | write a comprehension or use the spread
72 | operator.
73 |
74 | */
75 |
76 | shared void namedArgListsWithComprehensionArgs() {
77 | value hello = String { for (c in "HELLO") c.lowercased };
78 | value immutableSet = set { "never", "once", "twice", "thrice" };
79 | value hashSet = HashSet { *(-1..1) };
80 | value hashMap = HashMap { *immutableSet.indexed };
81 | print(hello);
82 | print(immutableSet);
83 | print(hashSet);
84 | print(hashMap);
85 | }
86 |
87 | /*
88 |
89 | We can pass a function as an argument using
90 | a very natural syntax.
91 |
92 | */
93 |
94 | shared void namedFunctionalArg() {
95 | value iter = mapPairs {
96 | firstIterable = 1..5;
97 | secondIterable = {
98 | "once",
99 | "twice",
100 | "thrice",
101 | "four times",
102 | "five times"
103 | };
104 | function collecting(Integer num, String word)
105 | => num -> word + " hello".repeat(num);
106 | };
107 | print(iter);
108 | }
109 |
110 | /*
111 |
112 | All this seems like a lot of new syntax! But
113 | there's a deeper purpose behind it: named
114 | argument lists provide us with a very
115 | flexible syntax for defining tree-like
116 | structures. This has many applications, from
117 | build scripts to user interfaces.
118 |
119 | The following classes define the "schema" of
120 | a mini-language for defining tables.
121 |
122 | */
123 |
124 | String center(String content, Integer size) {
125 | value padding = size-content.size;
126 | value paddingBefore = padding/2;
127 | value paddingAfter = padding-paddingBefore;
128 | return " ".repeat(paddingBefore) + content +
129 | " ".repeat(paddingAfter);
130 | }
131 |
132 | class Cell({String*} content) {
133 | shared actual String string {
134 | value result = StringBuilder();
135 | for (s in content) {
136 | result.append(s);
137 | }
138 | return result.string;
139 | }
140 | }
141 |
142 | class Row({Cell*} cell) {
143 | shared Cell[] cells = cell.sequence();
144 | shared actual String string {
145 | value result = StringBuilder();
146 | result.append("|");
147 | for (cell in cells) {
148 | result.append(center(cell.string, 45));
149 | result.append("|");
150 | }
151 | return result.string;
152 | }
153 | }
154 |
155 | class Table(String title, Row header, {Row*} rows) {
156 | shared actual String string {
157 | value result = StringBuilder();
158 | value size = header.cells.size*46+1;
159 | result.append(center(title, size) + "\n");
160 | result.append(center("-".repeat(title.size), size) + "\n");
161 | result.append(header.string.replace("|", " ")+"\n");
162 | result.append("-".repeat(size) + "\n");
163 | for (row in rows) {
164 | result.append(row.string+"\n");
165 | result.append("-".repeat(row.cells.size*46+1) + "\n");
166 | }
167 | return result.string;
168 | }
169 | }
170 |
171 | /*
172 |
173 | Now we can define a table using a very
174 | natural syntax, where the code represents
175 | the structure of the table itself:
176 |
177 | */
178 |
179 | Table table = Table {
180 | title = "Ceylon Project";
181 | header = Row {
182 | Cell { "Module" },
183 | Cell { "Description" },
184 | Cell { "URL" }
185 | };
186 | Row {
187 | Cell { "ceylon-spec" },
188 | Cell { "The specification and typechecker" },
189 | Cell { "https://github.com/ceylon/ceylon-spec" }
190 | },
191 | Row {
192 | Cell { "ceylon-compiler" },
193 | Cell { "The backend for the JVM" },
194 | Cell { "https://github.com/ceylon/ceylon-compiler" }
195 | },
196 | Row {
197 | Cell { "ceylon-js" },
198 | Cell { "The backend for JavaScript" },
199 | Cell { "https://github.com/ceylon/ceylon-js" }
200 | },
201 | Row {
202 | Cell { "ceylon.language" },
203 | Cell { "The language module" },
204 | Cell { "https://github.com/ceylon/ceylon.language" }
205 | }
206 | };
207 |
208 | shared void printTable() {
209 | print(table);
210 | }
--------------------------------------------------------------------------------
/source/es/06interfaces_operadores.ceylon:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Una interfaz define un contrato que puede ser
4 | satisfecho por una clase. Las interfaces pueden
5 | tener miembros formales, o incluso miembros
6 | concretos:
7 |
8 | - métodos,
9 | - getters y setters, y
10 | - clases miembro.
11 |
12 | Pero una interfaz no puede:
13 |
14 | - tener un atributo que mantenga una referencia
15 | a un valor, o
16 | - definir lógica de inicialización.
17 |
18 | Por tanto, decimos que las interfaces no tienen
19 | estado. Esto significa que la herencia "diamante"
20 | no es un problema en Ceylon.
21 |
22 | */
23 |
24 | interface Writer {
25 |
26 | shared formal void write(String string);
27 |
28 | shared void writeLine(String string) {
29 | write(string + operatingSystem.newline);
30 | }
31 |
32 | }
33 |
34 | /*
35 |
36 | Una clase puede satisfacer la interfaz,
37 | heredando sus miembros.
38 |
39 | */
40 |
41 | class FunctionWriter(void fun(String string))
42 | satisfies Writer {
43 | write = fun;
44 | }
45 |
46 | shared void testFunctionWriter() {
47 | FunctionWriter(process.write).writeLine("Hello!");
48 | FunctionWriter(process.writeError).writeLine("Ooops!");
49 | }
50 |
51 | /*
52 |
53 | Una clase puede satisfacer múltiples interfaces.
54 | Usamos el símbolo & para separar los supertipos
55 | porque conceptualmente forman una intersección
56 | de tipos.
57 |
58 | */
59 |
60 | class TextWriter(StringBuilder stringBuilder)
61 | satisfies Writer & Category<> {
62 |
63 | contains(Object element)
64 | => element in stringBuilder.string;
65 |
66 | write(String string)
67 | => stringBuilder.append(string);
68 |
69 | }
70 |
71 | shared void testTextWriter() {
72 |
73 | value textWriter = TextWriter(StringBuilder());
74 | textWriter.writeLine("Hello :-)");
75 | textWriter.writeLine("Goodbye :-(");
76 |
77 | // "x in category" significa "category.contains(x)"
78 | // donde category es una instancia de Category
79 | assert(":-)" in textWriter);
80 |
81 | }
82 |
83 | /*
84 |
85 | Es especialmente común tener clases anónimas
86 | que satisfacen una interfaz.
87 |
88 | */
89 |
90 | object consoleWriter satisfies Writer {
91 | write = process.write;
92 | }
93 |
94 | shared void testConsoleWriter() {
95 | consoleWriter.writeLine("Hello!");
96 | consoleWriter.writeLine("Bye!");
97 | }
98 |
99 | /*
100 |
101 | La clase anónima de arriba es un singleton,
102 | porque está declarada en el primer nivel. Pero
103 | no todas las clases anónimas son singleton.
104 |
105 | */
106 |
107 | //esta clase anónima es un singleton
108 | object naturals
109 | satisfies Iterable {
110 |
111 | shared actual Iterator iterator() {
112 | //una nueva instancia de esta clase
113 | //anónima se crea cada vez que se llama
114 | //a iterator()
115 | object iterator
116 | satisfies Iterator {
117 | variable value int = 1;
118 | next() => int++;
119 | }
120 | return iterator;
121 | }
122 |
123 | }
124 |
125 | /*
126 |
127 | La clase anónima de arriba satisface Iterable.
128 | Esto significa que podemos iterarla con un
129 | bucle for.
130 |
131 | */
132 |
133 | shared void loop() {
134 | for (n in naturals) {
135 | print(n);
136 | }
137 | }
138 |
139 | /*
140 |
141 | Muchas de las construcciones intrínsecas al
142 | lenguaje se definen en términos de interfaces
143 | que tus propias clases pueden implementar.
144 | En particular, la mayoría de los operadores se
145 | definen en términos de interfaces.
146 |
147 | Veamos como podemos definir un tipo "número
148 | complejo" que funcione exactamente igual que
149 | los tipos numéricos intrínsecos.
150 |
151 | */
152 |
153 | "A complex number class demonstrating operator
154 | polymorphism in Ceylon."
155 | class Complex(shared Float re, shared Float im=0.0)
156 | satisfies Exponentiable {
157 |
158 | negated => Complex(-re,-im);
159 |
160 | plus(Complex other) => Complex(re+other.re, im+other.im);
161 |
162 | minus(Complex other) => Complex(re-other.re, im-other.im);
163 |
164 | times(Complex other) =>
165 | Complex(re*other.re-im*other.im,
166 | re*other.im+im*other.re);
167 |
168 | shared actual Complex divided(Complex other) {
169 | Float d = other.re^2 + other.im^2;
170 | return Complex((re*other.re+im*other.im)/d,
171 | (im*other.re-re*other.im)/d);
172 | }
173 |
174 | "Accepts non-negative powers."
175 | shared actual Complex power(Integer other) {
176 | "exponent must be non-negative"
177 | assert(other>=0);
178 | //impl pobre
179 | variable Complex result = Complex(1.0, 0.0);
180 | for (i in 0:other) {
181 | result*=this;
182 | }
183 | return result;
184 | }
185 |
186 | string => im<0.0 then "``re``-``-im``i"
187 | else "``re``+``im``i";
188 |
189 | hash => re.hash + im.hash;
190 |
191 | shared actual Boolean equals(Object that) {
192 | if (is Complex that) {
193 | return re==that.re && im==that.im;
194 | }
195 | else {
196 | return false;
197 | }
198 | }
199 |
200 | }
201 |
202 | Complex i = Complex(0.0, 1.0);
203 |
204 | shared void testComplex() {
205 |
206 | Complex one = Complex(1.0);
207 | Complex zero = Complex(0.0);
208 |
209 | Complex sum = one+i+zero;
210 | assert (sum==Complex(1.0, 1.0));
211 |
212 | Complex zeroProduct = one*zero;
213 | assert (zeroProduct==zero);
214 |
215 | Complex nonzeroProduct = one*i;
216 | assert (nonzeroProduct==i);
217 |
218 | Complex diff = -one-zero-i;
219 | assert (diff==Complex(-1.0, -1.0));
220 |
221 | Complex power = i^3;
222 | assert (power==Complex(-0.0, -1.0));
223 |
224 | Complex quot = one/i;
225 | assert(quot==-i);
226 |
227 | }
228 |
229 | /*
230 |
231 | EJERCICIO
232 |
233 | Escribe una clase Vector, que soporte suma de
234 | vectores con + (a través de la interfaz
235 | Summable) y producto escalar con ** (a través
236 | de la interfaz Scalable).
237 |
238 | */
--------------------------------------------------------------------------------
/source/es/07argumentos_con_nombre.ceylon:
--------------------------------------------------------------------------------
1 | import ceylon.collection {
2 | HashSet,
3 | HashMap
4 | }
5 | /*
6 |
7 | Cuando una función tiene muchos parámetros, es
8 | mejor listar sus argumentos por nombre. Los
9 | argumentos con nombre van rodeados por llaves,
10 | y cada argumento individual se separa por punto
11 | y coma.
12 |
13 | */
14 |
15 | shared void namedArgLists() {
16 | value entry1 = Entry { key = 1; item = "once"; };
17 | value entry2 = Entry { item = "twice"; key = 2; };
18 | value int1 = Integer.parse { string = "1000101"; radix = 2; };
19 | value int2 = Integer.parse { radix = 16; string = "1000101"; };
20 | print(entry1);
21 | print(entry2);
22 | print(int1);
23 | print(int2);
24 | }
25 |
26 | /*
27 |
28 | Incluso dentro de una lista de argumentos con
29 | nombre, se permite listar los primeros
30 | argumentos posicionalmente. (La razón para esto
31 | quedará más clara más abajo.)
32 |
33 | */
34 |
35 | shared void namedArgListsWithPositionalArgs() {
36 | Entry { 1; item = "once"; };
37 | Entry { 2; "twice"; };
38 | Integer.parse { "1000101"; radix = 2; };
39 | Integer.parse { "1000101"; 16; };
40 | }
41 |
42 | /*
43 |
44 | Al final de una lista de argumentos con nombre,
45 | podemos listar argumentos adicionales, separados
46 | por comas, que se interpretan como argumentos al
47 | primer parámetro de tipo Iterable que no tenga
48 | ya un argumento.
49 |
50 | Esta es la sintaxis que habitualmente usamos para
51 | instanciar tipos contenedor con una lista fija
52 | inicial de elementos.
53 |
54 | */
55 |
56 | shared void namedArgListsWithIterableArgs() {
57 | value hello = String { 'H', 'e', 'l', 'l', 'o' };
58 | value immutableSet = set { "once", "twice", "thrice" };
59 | value hashSet = HashSet { 0, 1, -1 };
60 | value hashMap = HashMap { 1->"once", 2->"twice", 3->"thrice", 0->"never" };
61 | print(hello);
62 | print(immutableSet);
63 | print(hashSet);
64 | print(hashMap);
65 | }
66 |
67 | /*
68 |
69 | En Ceylon, donde se pueda escribir una lista de
70 | valores de longitud arbitraria, también se puede
71 | escribir una comprensión o utilizar el operador
72 | desplegar.
73 |
74 | */
75 |
76 | shared void namedArgListsWithComprehensionArgs() {
77 | value hello = String { for (c in "HELLO") c.lowercased };
78 | value immutableSet = set { "never", "once", "twice", "thrice" };
79 | value hashSet = HashSet { *(-1..1) };
80 | value hashMap = HashMap { *immutableSet.indexed };
81 | print(hello);
82 | print(immutableSet);
83 | print(hashSet);
84 | print(hashMap);
85 | }
86 |
87 | /*
88 |
89 | Podemos pasar una función como un argumento
90 | utilizando una sintaxis muy natural.
91 |
92 | */
93 |
94 | shared void namedFunctionalArg() {
95 | value iter = mapPairs {
96 | firstIterable = 1..5;
97 | secondIterable = {
98 | "once",
99 | "twice",
100 | "thrice",
101 | "four times",
102 | "five times"
103 | };
104 | function collecting(Integer num, String word)
105 | => num -> word + " hello".repeat(num);
106 | };
107 | print(iter);
108 | }
109 |
110 | /*
111 |
112 | ¡Todo esto parece un montón de nueva sintaxis!
113 | Pero hay un propósito más profundo detrás de
114 | ello: las listas de argumentos con nombre nos
115 | proporcionan una sintaxis muy flexible para
116 | definir estructuras con forma de árbol. Esto
117 | tiene muchas aplicaciones, desde scripts de
118 | construcción a interfaces de usuario.
119 |
120 | Las siguientes clases definen el "esquema" de
121 | un mini-lenguaje para definir tablas.
122 |
123 | */
124 |
125 | String center(String content, Integer size) {
126 | value padding = size-content.size;
127 | value paddingBefore = padding/2;
128 | value paddingAfter = padding-paddingBefore;
129 | return " ".repeat(paddingBefore) + content +
130 | " ".repeat(paddingAfter);
131 | }
132 |
133 | class Cell({String*} content) {
134 | shared actual String string {
135 | value result = StringBuilder();
136 | for (s in content) {
137 | result.append(s);
138 | }
139 | return result.string;
140 | }
141 | }
142 |
143 | class Row({Cell*} cell) {
144 | shared Cell[] cells = cell.sequence();
145 | shared actual String string {
146 | value result = StringBuilder();
147 | result.append("|");
148 | for (cell in cells) {
149 | result.append(center(cell.string, 45));
150 | result.append("|");
151 | }
152 | return result.string;
153 | }
154 | }
155 |
156 | class Table(String title, Row header, {Row*} rows) {
157 | shared actual String string {
158 | value result = StringBuilder();
159 | value size = header.cells.size*46+1;
160 | result.append(center(title, size) + "\n");
161 | result.append(center("-".repeat(title.size), size) + "\n");
162 | result.append(header.string.replace("|", " ")+"\n");
163 | result.append("-".repeat(size) + "\n");
164 | for (row in rows) {
165 | result.append(row.string+"\n");
166 | result.append("-".repeat(row.cells.size*46+1) + "\n");
167 | }
168 | return result.string;
169 | }
170 | }
171 |
172 | /*
173 |
174 | Ahora podemos definir una tabla utilizando una
175 | sintaxis muy natural, donde el código
176 | representa la estructura de la tabla en sí:
177 |
178 | */
179 |
180 | Table table = Table {
181 | title = "Ceylon Project";
182 | header = Row {
183 | Cell { "Module" },
184 | Cell { "Description" },
185 | Cell { "URL" }
186 | };
187 | Row {
188 | Cell { "ceylon-spec" },
189 | Cell { "The specification and typechecker" },
190 | Cell { "https://github.com/ceylon/ceylon-spec" }
191 | },
192 | Row {
193 | Cell { "ceylon-compiler" },
194 | Cell { "The backend for the JVM" },
195 | Cell { "https://github.com/ceylon/ceylon-compiler" }
196 | },
197 | Row {
198 | Cell { "ceylon-js" },
199 | Cell { "The backend for JavaScript" },
200 | Cell { "https://github.com/ceylon/ceylon-js" }
201 | },
202 | Row {
203 | Cell { "ceylon.language" },
204 | Cell { "The language module" },
205 | Cell { "https://github.com/ceylon/ceylon.language" }
206 | }
207 | };
208 |
209 | shared void printTable() {
210 | print(table);
211 | }
--------------------------------------------------------------------------------
/source/fr/06interfaces_operateurs.ceylon:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Une interface définie un contrat qui peut être
4 | satisfait par une classe. Les interfaces peuvent
5 | avoir des membres formels, ou même des membres
6 | concrets :
7 |
8 | - méthodes,
9 | - getters et setters, et
10 | - classes membres.
11 |
12 | Mais une interface ne peux pas :
13 |
14 | - avoir un attribut qui conserve une référence
15 | sur une valeur, ou
16 | - définir une logique d'initialisation.
17 |
18 | Ainsi, nous pouvons dire que les interfaces
19 | sont sans état. Cela signifie que les héritages
20 | en "diamant" ne sont pas un problème en Ceylon.
21 |
22 | */
23 |
24 | interface Writer {
25 |
26 | shared formal void write(String string);
27 |
28 | shared void writeLine(String string) {
29 | write(string + operatingSystem.newline);
30 | }
31 |
32 | }
33 |
34 | /*
35 |
36 | Une classe peut satisfaire une interface,
37 | héritant alors de ses membres.
38 |
39 | */
40 |
41 | class FunctionWriter(void fun(String string))
42 | satisfies Writer {
43 | write = fun;
44 | }
45 |
46 | shared void testFunctionWriter() {
47 | FunctionWriter(process.write).writeLine("Hello!");
48 | FunctionWriter(process.writeError).writeLine("Ooops!");
49 | }
50 |
51 | /*
52 |
53 | Une classe peut satisfaire plusieurs interfaces.
54 | Nous utilisons le symbole & pour séparer les
55 | supertypes car conceptuellement ils forment
56 | une intersection de types.
57 |
58 | */
59 |
60 | class TextWriter(StringBuilder stringBuilder)
61 | satisfies Writer & Category<> {
62 |
63 | contains(Object element)
64 | => element in stringBuilder.string;
65 |
66 | write(String string)
67 | => stringBuilder.append(string);
68 |
69 | }
70 |
71 | shared void testTextWriter() {
72 |
73 | value textWriter = TextWriter(StringBuilder());
74 | textWriter.writeLine("Hello :-)");
75 | textWriter.writeLine("Goodbye :-(");
76 |
77 | // "x in category" signifie "category.contains(x)"
78 | // où category est une instance de Category
79 | assert(":-)" in textWriter);
80 |
81 | }
82 |
83 | /*
84 |
85 | Il est particulièrement répandu d'avoir des
86 | classes anonymes qui satisfont une interface.
87 |
88 | */
89 |
90 | object consoleWriter satisfies Writer {
91 | write = process.write;
92 | }
93 |
94 | shared void testConsoleWriter() {
95 | consoleWriter.writeLine("Hello!");
96 | consoleWriter.writeLine("Bye!");
97 | }
98 |
99 | /*
100 |
101 | La classe anonyme ci-dessus est un singleton,
102 | car sa déclaration est au premier niveau.
103 | Néanmoins, toutes les classes anonymes ne sont
104 | pas des singletons.
105 |
106 | */
107 |
108 | //cette classe anonyme est un singleton
109 | object naturals
110 | satisfies Iterable {
111 |
112 | shared actual Iterator iterator() {
113 | //une nouvelle instance de cette classes
114 | //anonyme est créée à chaque fois que
115 | //iterator() est appelé
116 | object iterator
117 | satisfies Iterator {
118 | variable value int = 1;
119 | next() => int++;
120 | }
121 | return iterator;
122 | }
123 |
124 | }
125 |
126 | /*
127 |
128 | La classe anonyme ci-dessus satisfait Iterable.
129 | Nous pouvons donc l'itérer avec une boucle for.
130 |
131 | */
132 |
133 | shared void loop() {
134 | for (n in naturals) {
135 | print(n);
136 | }
137 | }
138 |
139 | /*
140 |
141 | De nombreuses constructions syntaxiques intégrées
142 | au langage sont définies via des interfaces
143 | que vos propres classes peuvent implémenter.
144 | En particulier, la plupart des opérateurs
145 | sont définis en termes d'interfaces.
146 |
147 | Voyons comment définir un type de nombre
148 | complexe qui fonctionne de la même manière
149 | que les types numériques fournis par le
150 | langage.
151 |
152 | */
153 |
154 | "Une classes de nombre complexe illustrant le
155 | polymorphisme d'opérateur en Ceylon"
156 | class Complex(shared Float re, shared Float im=0.0)
157 | satisfies Exponentiable {
158 |
159 | negated => Complex(-re,-im);
160 |
161 | plus(Complex other) => Complex(re+other.re, im+other.im);
162 |
163 | minus(Complex other) => Complex(re-other.re, im-other.im);
164 |
165 | times(Complex other) =>
166 | Complex(re*other.re-im*other.im,
167 | re*other.im+im*other.re);
168 |
169 | shared actual Complex divided(Complex other) {
170 | Float d = other.re^2 + other.im^2;
171 | return Complex((re*other.re+im*other.im)/d,
172 | (im*other.re-re*other.im)/d);
173 | }
174 |
175 | "Accepte des puissances non-négatives"
176 | shared actual Complex power(Integer other) {
177 | "L'exposant doit être non-négatif"
178 | assert(other>=0);
179 | //impl simpliste
180 | variable Complex result = Complex(1.0, 0.0);
181 | for (i in 0:other) {
182 | result*=this;
183 | }
184 | return result;
185 | }
186 |
187 | string => im<0.0 then "``re``-``-im``i"
188 | else "``re``+``im``i";
189 |
190 | hash => re.hash + im.hash;
191 |
192 | shared actual Boolean equals(Object that) {
193 | if (is Complex that) {
194 | return re==that.re && im==that.im;
195 | }
196 | else {
197 | return false;
198 | }
199 | }
200 |
201 | }
202 |
203 | Complex i = Complex(0.0, 1.0);
204 |
205 | shared void testComplex() {
206 |
207 | Complex one = Complex(1.0);
208 | Complex zero = Complex(0.0);
209 |
210 | Complex sum = one+i+zero;
211 | assert (sum==Complex(1.0, 1.0));
212 |
213 | Complex zeroProduct = one*zero;
214 | assert (zeroProduct==zero);
215 |
216 | Complex nonzeroProduct = one*i;
217 | assert (nonzeroProduct==i);
218 |
219 | Complex diff = -one-zero-i;
220 | assert (diff==Complex(-1.0, -1.0));
221 |
222 | Complex power = i^3;
223 | assert (power==Complex(-0.0, -1.0));
224 |
225 | Complex quot = one/i;
226 | assert(quot==-i);
227 |
228 | }
229 |
230 | /*
231 |
232 | EXERCICE
233 |
234 | Ecrire une classe Vector, qui supporte l'addition vectorielle
235 | avec + (via l'interface Summable) et le produit scalaire
236 | avec ** (via l'interface Scalable).
237 |
238 | */
--------------------------------------------------------------------------------
/source/de/07benannte_argumente.ceylon:
--------------------------------------------------------------------------------
1 | import ceylon.collection {
2 | HashSet,
3 | HashMap
4 | }
5 | /*
6 |
7 | Wenn eine Funktion viele Parameter hat, ist es
8 | oft besser, ihre Argumente mit Namen versehen
9 | zu notieren. Listen benannter Argumente werden
10 | in geschweifen Klammern eingeschlossen, und die
11 | einzelnen Argumente sind durch Strichpunkte
12 | getrennt.
13 |
14 | */
15 |
16 | shared void namedArgLists() {
17 | value entry1 = Entry { key = 1; item = "einmal"; };
18 | value entry2 = Entry { item = "zweimal"; key = 2; };
19 | value int1 = Integer.parse { string = "1000101"; radix = 2; };
20 | value int2 = Integer.parse { radix = 16; string = "1000101"; };
21 | print(entry1);
22 | print(entry2);
23 | print(int1);
24 | print(int2);
25 | }
26 |
27 | /*
28 |
29 | Selbst innerhalb einer Liste benannter Argumente
30 | dürfen wir die ersten Argumente nur nach ihrer
31 | Position auflisten. (Der Grund dafür wird gleich
32 | klar.)
33 |
34 | */
35 |
36 | shared void namedArgListsWithPositionalArgs() {
37 | Entry { 1; item = "einmal"; };
38 | Entry { 2; "zweimal"; };
39 | Integer.parse { "1000101"; radix = 2; };
40 | Integer.parse { "1000101"; 16; };
41 | }
42 |
43 | /*
44 |
45 | Am Ende einer Liste benannter Argumente dürfen
46 | wir zusätzliche Argumente angeben, durch Kommas
47 | getrennt, die als Argumente für den ersten
48 | Parameter vom Typ Iterable, der noch kein
49 | Argument hat, gelten.
50 |
51 | Das ist die Syntax, die wir meist verwenden,
52 | um Container-Typen mit einer anfangs festen
53 | Menge an Elementen zu instanziieren.
54 |
55 | */
56 |
57 | shared void namedArgListsWithIterableArgs() {
58 | value hallo = String { 'H', 'a', 'l', 'l', 'o' };
59 | value immutableSet = set { "einmal", "zweimal", "dreimal" };
60 | value hashSet = HashSet { 0, 1, -1 };
61 | value hashMap = HashMap { 1->"einmal", 2->"zweimal", 3->"dreimal", 0->"nie" };
62 | print(hallo);
63 | print(immutableSet);
64 | print(hashSet);
65 | print(hashMap);
66 | }
67 |
68 | /*
69 |
70 | In Ceylon können wir überall, wo wir eine
71 | beliebig lange Liste von Werten angeben können,
72 | auch eine Comprehension oder den Verteilungs-
73 | Operator verwenden.
74 |
75 | */
76 |
77 | shared void namedArgListsWithComprehensionArgs() {
78 | value hallo = String { for (c in "HALLO") c.lowercased };
79 | value immutableSet = set { "nie", "einmal", "zweimal", "dreimal" };
80 | value hashSet = HashSet { *(-1..1) };
81 | value hashMap = HashMap { *immutableSet.indexed };
82 | print(hallo);
83 | print(immutableSet);
84 | print(hashSet);
85 | print(hashMap);
86 | }
87 |
88 | /*
89 |
90 | Mit der folgenden, sehr natürlichen Syntax können
91 | wir eine Funktion als Argument übergeben.
92 |
93 | */
94 |
95 | shared void namedFunctionalArg() {
96 | value iter = mapPairs {
97 | firstIterable = 1..5;
98 | secondIterable = {
99 | "einmal",
100 | "zweimal",
101 | "dreimal",
102 | "viermal",
103 | "fünfmal"
104 | };
105 | function collecting(Integer num, String word)
106 | => num -> word + " Hallo".repeat(num);
107 | };
108 | print(iter);
109 | }
110 |
111 | /*
112 |
113 | Das sieht wie eine Menge neuer Syntax aus! Aber
114 | es gibt einen tieferen Sinn dahinter: Listen
115 | benannter Argument geben uns eine sehr flexible
116 | Syntax, um baumartige Strukturen zu definieren.
117 | Dafür gibt es viele Anwendungen, von Build-
118 | Skripten bis zu Benutzeroberflächen.
119 |
120 | Die folgenden Klassen definieren das "Schema" für
121 | eine Mini-Sprache, um Tabellen zu definieren.
122 |
123 | */
124 |
125 | String center(String content, Integer size) {
126 | value padding = size-content.size;
127 | value paddingBefore = padding/2;
128 | value paddingAfter = padding-paddingBefore;
129 | return " ".repeat(paddingBefore) + content +
130 | " ".repeat(paddingAfter);
131 | }
132 |
133 | class Cell({String*} content) {
134 | shared actual String string {
135 | value result = StringBuilder();
136 | for (s in content) {
137 | result.append(s);
138 | }
139 | return result.string;
140 | }
141 | }
142 |
143 | class Row({Cell*} cell) {
144 | shared Cell[] cells = cell.sequence();
145 | shared actual String string {
146 | value result = StringBuilder();
147 | result.append("|");
148 | for (cell in cells) {
149 | result.append(center(cell.string, 45));
150 | result.append("|");
151 | }
152 | return result.string;
153 | }
154 | }
155 |
156 | class Table(String title, Row header, {Row*} rows) {
157 | shared actual String string {
158 | value result = StringBuilder();
159 | value size = header.cells.size*46+1;
160 | result.append(center(title, size) + "\n");
161 | result.append(center("-".repeat(title.size), size) + "\n");
162 | result.append(header.string.replace("|", " ")+"\n");
163 | result.append("-".repeat(size) + "\n");
164 | for (row in rows) {
165 | result.append(row.string+"\n");
166 | result.append("-".repeat(row.cells.size*46+1) + "\n");
167 | }
168 | return result.string;
169 | }
170 | }
171 |
172 | /*
173 |
174 | Jetzt können wir eine Tabelle mit einer sehr
175 | natürlichen Syntax definieren, wobei der Code
176 | die Struktur der Tabelle selbst darstellt:
177 |
178 | */
179 |
180 | Table table = Table {
181 | title = "Ceylon-Project";
182 | header = Row {
183 | Cell { "Modul" },
184 | Cell { "Beschreibung" },
185 | Cell { "URL" }
186 | };
187 | Row {
188 | Cell { "ceylon-spec" },
189 | Cell { "Die Spezifikation und der Typechecker" },
190 | Cell { "https://github.com/ceylon/ceylon-spec" }
191 | },
192 | Row {
193 | Cell { "ceylon-compiler" },
194 | Cell { "Das Backend für die JVM" },
195 | Cell { "https://github.com/ceylon/ceylon-compiler" }
196 | },
197 | Row {
198 | Cell { "ceylon-js" },
199 | Cell { "Das Backend für JavaScript" },
200 | Cell { "https://github.com/ceylon/ceylon-js" }
201 | },
202 | Row {
203 | Cell { "ceylon.language" },
204 | Cell { "Das Sprachmodul" },
205 | Cell { "https://github.com/ceylon/ceylon.language" }
206 | }
207 | };
208 |
209 | shared void printTable() {
210 | print(table);
211 | }
212 |
--------------------------------------------------------------------------------
/source/de/06schnittstellen_operatoren.ceylon:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Eine Schnittstelle (interface) definiert einen
4 | Vertrag, der von einer Klasse erfüllt werden
5 | kann. Schnittstellen können Member definieren,
6 | die "formal" annotiert sind, oder sogar konkrete
7 | Member:
8 |
9 | - Methoden,
10 | - Getter und Setter, und
11 | - Member-Klassen.
12 |
13 | Aber eine Schnittstelle kann nicht
14 |
15 | - ein Attribut, das einen Verweis auf einen Wert
16 | enthält, haben, oder
17 | - Initialisierungslogik definieren.
18 |
19 | Deshalb nennen wir Schnittstellen zustandslos.
20 | Das bedeutet, dass "Rauten-Vererbung" in Ceylon
21 | kein Problem darstellt.
22 |
23 | */
24 |
25 | interface Writer {
26 |
27 | shared formal void write(String string);
28 |
29 | shared void writeLine(String string) {
30 | write(string + operatingSystem.newline);
31 | }
32 |
33 | }
34 |
35 | /*
36 |
37 | Eine Klasse kann eine Schnittstelle erfüllen und
38 | ihre Member erben.
39 |
40 | */
41 |
42 | class FunctionWriter(void fun(String string))
43 | satisfies Writer {
44 | write = fun;
45 | }
46 |
47 | shared void testFunctionWriter() {
48 | FunctionWriter(process.write).writeLine("Hallo!");
49 | FunctionWriter(process.writeError).writeLine("Uups!");
50 | }
51 |
52 | /*
53 |
54 | Eine Klasse kann mehrere Schnittstellen erfüllen.
55 | Wir verwenden das '&'-Symbol, um die erfüllten
56 | Schnittstellen zu trennen, weil sie prinzipiell
57 | einen Schnitttyp darstellen.
58 |
59 | */
60 |
61 | class TextWriter(StringBuilder stringBuilder)
62 | satisfies Writer & Category<> {
63 |
64 | contains(Object element)
65 | => element in stringBuilder.string;
66 |
67 | write(String string)
68 | => stringBuilder.append(string);
69 |
70 | }
71 |
72 | shared void testTextWriter() {
73 |
74 | value textWriter = TextWriter(StringBuilder());
75 | textWriter.writeLine("Hallo :-)");
76 | textWriter.writeLine("Tschüss :-(");
77 |
78 | // "x in category" heißt "category.contains(x)"
79 | // wobei category eine Instanz von Category ist
80 | assert(":-)" in textWriter);
81 |
82 | }
83 |
84 | /*
85 |
86 | Es ist besonders häufig, anonyme Klassen zu haben,
87 | die eine Schnittstelle erfüllen.
88 |
89 | */
90 |
91 | object consoleWriter satisfies Writer {
92 | write = process.write;
93 | }
94 |
95 | shared void testConsoleWriter() {
96 | consoleWriter.writeLine("Hallo!");
97 | consoleWriter.writeLine("Tschüss!");
98 | }
99 |
100 | /*
101 |
102 | Die obige anonyme Klasse ist ein Singleton
103 | (Einweg-Objekt), weil die Deklaration auf oberster
104 | Ebene steht und nicht verschachtelt ist. Aber
105 | nicht jede anonyme Klasse ist ein Singleton.
106 |
107 | */
108 |
109 | // Diese anonyme Klasse ist ein Singleton
110 | object naturals
111 | satisfies Iterable {
112 |
113 | shared actual Iterator iterator() {
114 | // Jedes Mal, wenn iterator() aufgerufen
115 | // wird, wird eine neue Instanz dieser
116 | // anonymen Klasse erstellt
117 | object iterator
118 | satisfies Iterator {
119 | variable value int = 1;
120 | next() => int++;
121 | }
122 | return iterator;
123 | }
124 |
125 | }
126 |
127 | /*
128 |
129 | Die obige anonyme Klasse erfüllt Iterable.
130 | Damit können wir sie mit einer for-Schleife
131 | durchlaufen.
132 |
133 | */
134 |
135 | shared void loop() {
136 | for (n in naturals) {
137 | print(n);
138 | }
139 | }
140 |
141 | /*
142 |
143 | Viele der "eingebauten" Sprachkonstrukte sind
144 | über Schnittstellen definiert, die deine eigenen
145 | Klassen erfüllen können. Insbesondere sind fast
146 | alle Operatoren über Schnittstellen definiert.
147 |
148 | Schauen wir mal, wie wir einen Typ für komplexe
149 | Zahlen definieren können, der genauso wie die
150 | eingebauten numerischen Typen funktioniert.
151 |
152 | */
153 |
154 | "Eine Klasse für komplexe Zahlen, die
155 | Operatorpolymorphismus in Ceylon demonstriert."
156 | class Complex(shared Float re, shared Float im=0.0)
157 | satisfies Exponentiable {
158 |
159 | negated => Complex(-re,-im);
160 |
161 | plus(Complex other) => Complex(re+other.re, im+other.im);
162 |
163 | minus(Complex other) => Complex(re-other.re, im-other.im);
164 |
165 | times(Complex other) =>
166 | Complex(re*other.re-im*other.im,
167 | re*other.im+im*other.re);
168 |
169 | shared actual Complex divided(Complex other) {
170 | Float d = other.re^2 + other.im^2;
171 | return Complex((re*other.re+im*other.im)/d,
172 | (im*other.re-re*other.im)/d);
173 | }
174 |
175 | "Akzeptiert nichtnegative Exponenten."
176 | shared actual Complex power(Integer other) {
177 | "Exponent darf nicht negativ sein"
178 | assert(other>=0);
179 | // einfache, langsame Implementierung
180 | variable Complex result = Complex(1.0, 0.0);
181 | for (i in 0:other) {
182 | result*=this;
183 | }
184 | return result;
185 | }
186 |
187 | string => im<0.0 then "``re``-``-im``i"
188 | else "``re``+``im``i";
189 |
190 | hash => re.hash + im.hash;
191 |
192 | shared actual Boolean equals(Object that) {
193 | if (is Complex that) {
194 | return re==that.re && im==that.im;
195 | }
196 | else {
197 | return false;
198 | }
199 | }
200 |
201 | }
202 |
203 | Complex i = Complex(0.0, 1.0);
204 |
205 | shared void testComplex() {
206 |
207 | Complex one = Complex(1.0);
208 | Complex zero = Complex(0.0);
209 |
210 | Complex sum = one+i+zero;
211 | assert (sum==Complex(1.0, 1.0));
212 |
213 | Complex zeroProduct = one*zero;
214 | assert (zeroProduct==zero);
215 |
216 | Complex nonzeroProduct = one*i;
217 | assert (nonzeroProduct==i);
218 |
219 | Complex diff = -one-zero-i;
220 | assert (diff==Complex(-1.0, -1.0));
221 |
222 | Complex power = i^3;
223 | assert (power==Complex(-0.0, -1.0));
224 |
225 | Complex quot = one/i;
226 | assert(quot==-i);
227 |
228 | }
229 |
230 | /*
231 |
232 | ÜBUNG
233 |
234 | Schreibe eine Vektor-Klasse, die Vektoraddition
235 | mit + (über die Summable-Schnittstelle) und
236 | skalare Multiplikation mit ** (über die Scalable-
237 | Schnittstelle) unterstützt.
238 |
239 | */
240 |
--------------------------------------------------------------------------------
/source/fr/07arguments_nommes.ceylon:
--------------------------------------------------------------------------------
1 | import ceylon.collection {
2 | HashMap,
3 | HashSet
4 | }
5 | /*
6 |
7 | Quand une fonction a de nombreux paramètres,
8 | il vaut mieux lister ses arguments par nom.
9 | Les listes d'arguments nommés sont encadrées
10 | par des accolades, et les arguments eux même
11 | sont séparés par des points-virgules.
12 |
13 | */
14 |
15 | shared void namedArgLists() {
16 | value entry1 = Entry { key = 1; item = "once"; };
17 | value entry2 = Entry { item = "twice"; key = 2; };
18 | value int1 = Integer.parse { string = "1000101"; radix = 2; };
19 | value int2 = Integer.parse { radix = 16; string = "1000101"; };
20 | print(entry1);
21 | print(entry2);
22 | print(int1);
23 | print(int2);
24 | }
25 |
26 | /*
27 |
28 | Même à l'intérieur d'une liste d'arguments
29 | nommés, nous pouvons lister le premier
30 | élément de manière positionnelle. (La raison
31 | de cela sera explicité ci-dessous)
32 |
33 | */
34 |
35 | shared void namedArgListsWithPositionalArgs() {
36 | Entry { 1; item = "once"; };
37 | Entry { 2; "twice"; };
38 | Integer.parse { "1000101"; radix = 2; };
39 | Integer.parse { "1000101"; 16; };
40 | }
41 |
42 | /*
43 |
44 | A la fin d'une liste d'arguments nommés,
45 | nous pouvons lister des arguments
46 | additionnels, séparés par des virgules,
47 | qui sont interprétés en tant qu'arguments
48 | du premier paramètre de type Iterable qui
49 | n'a pas déjà un argument.
50 |
51 | C'est la syntaxe habituelle que nous
52 | utilisons pour instancier les types de
53 | container avec une liste initiale
54 | d'éléments.
55 |
56 | */
57 |
58 | shared void namedArgListsWithIterableArgs() {
59 | value hello = String { 'H', 'e', 'l', 'l', 'o' };
60 | value immutableSet = set { "once", "twice", "thrice" };
61 | value hashSet = HashSet { 0, 1, -1 };
62 | value hashMap = HashMap { 1->"once", 2->"twice", 3->"thrice", 0->"never" };
63 | print(hello);
64 | print(immutableSet);
65 | print(hashSet);
66 | print(hashMap);
67 | }
68 |
69 | /*
70 |
71 | En Ceylon, aux endroits où nous pouvons
72 | écrire une liste de valeurs de longueur
73 | arbitraire, nous pouvons également écrire
74 | une compréhension ou utiliser l'opérateur
75 | d'expansion.
76 |
77 | */
78 |
79 | shared void namedArgListsWithComprehensionArgs() {
80 | value hello = String { for (c in "HELLO") c.lowercased };
81 | value immutableSet = set { "never", "once", "twice", "thrice" };
82 | value hashSet = HashSet { *(-1..1) };
83 | value hashMap = HashMap { *immutableSet.indexed };
84 | print(hello);
85 | print(immutableSet);
86 | print(hashSet);
87 | print(hashMap);
88 | }
89 |
90 | /*
91 |
92 | Nous pouvons passer une fonction en tant
93 | qu'argument via une syntaxe très naturelle.
94 |
95 | */
96 |
97 | shared void namedFunctionalArg() {
98 | value iter = mapPairs {
99 | firstIterable = 1..5;
100 | secondIterable = {
101 | "once",
102 | "twice",
103 | "thrice",
104 | "four times",
105 | "five times"
106 | };
107 | function collecting(Integer num, String word)
108 | => num -> word + " hello".repeat(num);
109 | };
110 | print(iter);
111 | }
112 |
113 | /*
114 |
115 | Tout ceci semble représenter beaucoup de
116 | nouvelles syntaxes! Mais il y a un but plus
117 | profond derrière ceci : les listes
118 | d'arguments nommés nous fournissent un
119 | moyen extrêmement flexible pour définir
120 | des structures d'arbre. Ceci a de nombreuses
121 | applications, depuis les scripts de build
122 | jusqu'aux interfaces utilisateur.
123 |
124 | La classe suivante définit le "schema"
125 | d'un mini-langage pour définir des
126 | tables.
127 |
128 | */
129 |
130 | String center(String content, Integer size) {
131 | value padding = size-content.size;
132 | value paddingBefore = padding/2;
133 | value paddingAfter = padding-paddingBefore;
134 | return " ".repeat(paddingBefore) + content +
135 | " ".repeat(paddingAfter);
136 | }
137 |
138 | class Cell({String*} content) {
139 | shared actual String string {
140 | value result = StringBuilder();
141 | for (s in content) {
142 | result.append(s);
143 | }
144 | return result.string;
145 | }
146 | }
147 |
148 | class Row({Cell*} cell) {
149 | shared Cell[] cells = cell.sequence();
150 | shared actual String string {
151 | value result = StringBuilder();
152 | result.append("|");
153 | for (cell in cells) {
154 | result.append(center(cell.string, 45));
155 | result.append("|");
156 | }
157 | return result.string;
158 | }
159 | }
160 |
161 | class Table(String title, Row header, {Row*} rows) {
162 | shared actual String string {
163 | value result = StringBuilder();
164 | value size = header.cells.size*46+1;
165 | result.append(center(title, size) + "\n");
166 | result.append(center("-".repeat(title.size), size) + "\n");
167 | result.append(header.string.replace("|", " ")+"\n");
168 | result.append("-".repeat(size) + "\n");
169 | for (row in rows) {
170 | result.append(row.string+"\n");
171 | result.append("-".repeat(row.cells.size*46+1) + "\n");
172 | }
173 | return result.string;
174 | }
175 | }
176 |
177 | /*
178 |
179 | Maintenant nous pouvons définir une table
180 | en utilisant une syntaxe particulièrement
181 | intuitive, ou le code représente la
182 | structure de la table elle-même :
183 |
184 | */
185 |
186 | Table table = Table {
187 | title = "Ceylon Project";
188 | header = Row {
189 | Cell { "Module" },
190 | Cell { "Description" },
191 | Cell { "URL" }
192 | };
193 | Row {
194 | Cell { "ceylon-spec" },
195 | Cell { "The specification and typechecker" },
196 | Cell { "https://github.com/ceylon/ceylon-spec" }
197 | },
198 | Row {
199 | Cell { "ceylon-compiler" },
200 | Cell { "The backend for the JVM" },
201 | Cell { "https://github.com/ceylon/ceylon-compiler" }
202 | },
203 | Row {
204 | Cell { "ceylon-js" },
205 | Cell { "The backend for JavaScript" },
206 | Cell { "https://github.com/ceylon/ceylon-js" }
207 | },
208 | Row {
209 | Cell { "ceylon.language" },
210 | Cell { "The language module" },
211 | Cell { "https://github.com/ceylon/ceylon.language" }
212 | }
213 | };
214 |
215 | shared void printTable() {
216 | print(table);
217 | }
--------------------------------------------------------------------------------
/source/en/02classes.ceylon:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Every value is an instance of a class. The
4 | simplest classes just package together some
5 | related state into attributes.
6 |
7 | Classes have members:
8 |
9 | - parameters,
10 | - methods (member functions),
11 | - attributes (member values), and
12 | - member classes.
13 |
14 | Any member annotated shared forms part of the
15 | API of the class and may be accessed from
16 | outside the class.
17 |
18 | For simple classes, we usually need to refine
19 | members string, equals(), and hash that are
20 | inherited from the default supertype Basic.
21 |
22 | A member annotated actual refines a member of
23 | a supertype of the class.
24 |
25 | */
26 |
27 | class Time(shared Integer hour,
28 | shared Integer minute) {
29 |
30 | shared Integer secondsSinceMidnight =>
31 | minute%60*60 + hour*60*60;
32 |
33 | shared actual Integer hash =>
34 | secondsSinceMidnight;
35 |
36 | shared actual Boolean equals(Object that) {
37 | //the "is Time" construct tests and
38 | //narrows the type of a value
39 | if (is Time that) {
40 | //that is of type Time here
41 | return secondsSinceMidnight ==
42 | that.secondsSinceMidnight;
43 | }
44 | else {
45 | return false;
46 | }
47 | }
48 |
49 | //if writing "shared actual Type" gets too
50 | //boring, you can use this shortcut syntax!
51 | string => "``hour``:``minute``";
52 |
53 | }
54 |
55 | shared void tryOutTime() {
56 | Time time1 = Time(13,30);
57 | print(time1);
58 | Time time2 = Time(37,30);
59 | print(time2);
60 | Time time3 = Time(13,29);
61 | print(time2);
62 | print(time1==time2);
63 | print(time1==time3);
64 | print(time1.secondsSinceMidnight);
65 | }
66 |
67 | /*
68 |
69 | For testing classes, assertions are very
70 | useful. Run this function to see an assertion
71 | failure occur.
72 |
73 | */
74 |
75 | //TODO: get the assertions passing
76 | shared void testTime() {
77 | Time time1 = Time(13,30);
78 | assert (time1.string=="13:30");
79 | Time time2 = Time(37,30);
80 | assert (time2.string=="37:30");
81 | Time time3 = Time(13,29);
82 | assert (time3.string=="13:29");
83 | assert (time1==time2);
84 | assert (time1!=time3);
85 | assert (time1.secondsSinceMidnight==48600);
86 | }
87 |
88 | /*
89 |
90 | EXERCISE
91 |
92 | Fix the Time class so that all the assertions
93 | pass.
94 |
95 | */
96 |
97 | /*
98 |
99 | Some classes have mutable state. If an attribute
100 | is mutable, it must be annotated variable.
101 |
102 | */
103 |
104 | class Counter(count=0) {
105 | shared variable Integer count;
106 | shared void inc() => count++;
107 | string => count.string;
108 | }
109 |
110 | shared void testCounter() {
111 | value counter = Counter();
112 | assert (counter.count==0);
113 | counter.inc();
114 | counter.inc();
115 | assert (counter.count==2);
116 | counter.count = 0;
117 | assert (counter.count==0);
118 | }
119 |
120 | /*
121 |
122 | EXERCISE
123 |
124 | Add a reset() method to Counter.
125 |
126 | If you're clever, you can get the IDE to
127 | write almost all the code for you. First
128 | uncomment the test code below, and notice
129 | the error span. Hover over the error span
130 | to see the error message.
131 |
132 | Now, position the caret inside the error
133 | span, and let the IDE propose a partial
134 | fix by:
135 |
136 | - In IntelliJ:
137 |
138 | clicking the red lightbulb icon
139 |
140 | - In Eclipse:
141 |
142 | selecting Source > Quick Fix/Assist
143 |
144 | */
145 |
146 | //TODO: uncomment this test and get it to pass
147 | //shared void testReset() {
148 | // value counter = Counter();
149 | // assert (counter.count==0);
150 | // counter.inc();
151 | // counter.inc();
152 | // assert (counter.count==2);
153 | // counter.reset();
154 | // assert (counter.count==0);
155 | //}
156 |
157 | /*
158 |
159 | A subclass may extend our class, and refine
160 | its members. A class member may be refined if
161 | it is annotated default.
162 |
163 | */
164 |
165 | class SecondTime(Integer hour,
166 | Integer minute,
167 | second)
168 | extends Time(hour, minute) {
169 |
170 | //We can declare the type and annotations
171 | //of a parameter in the body of the class
172 | //to clean up the parameter list.
173 | shared Integer second;
174 |
175 | /*
176 |
177 | Ooops! The following code contains an error!
178 |
179 | First uncomment the code, and then fix the
180 | error by adding a 'default' annotation to
181 | Time.secondsSinceMidnight, above.
182 |
183 | */
184 |
185 | //TODO: uncomment and fix the error!
186 | //secondsSinceMidnight =>
187 | // super.secondsSinceMidnight+second%60;
188 |
189 | }
190 |
191 | /*
192 |
193 | EXERCISE
194 |
195 | Fix the implementation of Time and SecondTime
196 | so that the following tests pass.
197 |
198 | */
199 |
200 | //TODO: get the assertions passing
201 | shared void testSecondTime() {
202 | Time time = Time(13,30);
203 | assert (time.string=="13:30");
204 | SecondTime stime1 = SecondTime(13,30,00);
205 | SecondTime stime2 = SecondTime(13,30,25);
206 | assert (time==stime1);
207 | assert (time!=stime2);
208 | assert (stime1.string=="13:30:00");
209 | assert (stime2.string=="13:30:25");
210 | }
211 |
212 | /*
213 |
214 | An anonymous class declaration defines an
215 | instance. It's a combination value and
216 | class declaration.
217 |
218 | */
219 |
220 | object midnight extends SecondTime(0,0,0) {
221 | //TODO: uncomment and fix the error
222 | //string => "midnight";
223 | }
224 |
225 | /*
226 |
227 | An abstract class is a class which can't be
228 | instantiated. It may declare formal members,
229 | which must be implemented by concrete
230 | subclasses of the abstract class.
231 |
232 | An enumerated type is an abstract class or
233 | interface which enumerates (restricts) its
234 | subtypes.
235 |
236 | */
237 |
238 | abstract class LinkedList()
239 | of Cons | empty {
240 | shared formal Integer length;
241 | }
242 |
243 | //this case of the enumerated type is a class
244 | class Cons(shared T first,
245 | shared LinkedList rest)
246 | extends LinkedList() {
247 | length=>rest.length+1;
248 | }
249 |
250 | //this case of the enumerated type is a
251 | //singleton object
252 | object empty
253 | extends LinkedList() {
254 | length=>0;
255 | }
256 |
257 | String formatLinkedList(LinkedList