Continue with the Basics by Example; today's version of the post written in Fantom Enjoy!
You can copy and paste the code below in your favorite IDE/Editor and start playing and learning with it. This little "working" program will teach you the basics of the Programming Language.
There are some "comments" on the code added just to tell you what are or how are some features called. In case you want to review the theory, you can read my previous post, where I give a definition of each of the concepts mentioned on the code. You can find it here: http://carlosqt.blogspot.com/2010/08/new-series-languages-basics-by-example.html
Greetings Program - Verbose
// Fantom Basics internal class Greet { // Fields or Attributes private Str? message private Str? name private Int? loopMessage // Properties, Getters and Setters public Str Message { get { return this.&message } set { this.&message = this.capitalize(it) } } public Str Name { get { return this.&name } set { this.&name = this.capitalize(it) } } public Int LoopMessage { get { return this.&loopMessage } set { this.&loopMessage = it } } // Constructor public new make() { this.message = "" this.name = "" this.loopMessage = 0 } // Overloaded Constructor // No Overloaded Constructor support as designed // Method 1 private Str capitalize(Str val) { // "if-then-else" statement if (val.size() >= 1) { return val.capitalize() } else { return "" } } // Method 2 public Void salute() { // "for" statement for (i:=1; i<=this.loopMessage; i++) { echo("$this.message $this.name!") } } // Overloaded Method // No Overloaded Methods Support in Fantom. News methods instead. // Method 2.1 public Void salute21(Str message, Str name, Int loopMessage) { // "while" statement Int i := 0 while(i < loopMessage) { echo("${this.capitalize(message)} ${this.capitalize(name)}!") i++ } } // Method 2.2 public Void salute22(Str name) { // "switch/case" statement DateTime dtNow := DateTime.now(); switch(dtNow.hour) { case 6: case 7: case 8: case 9: case 10: case 11: this.message = "good morning," case 12: case 13: case 14: case 15: case 16: case 17: this.message = "good afternoon," case 18: case 19: case 20: case 21: case 22: this.message = "good evening," case 23: case 0: case 1: case 2: case 3: case 4: case 5: this.message = "good night," default: this.message = "huh?" } echo("${this.capitalize(this.message)} ${this.capitalize(name)}!") } } // Console Program public class FanGreetProgram { public static Void main() { // Define variable object of type Greet and Instantiate. Call Constructor Greet g := Greet.make() // Call Setters g.Message = "hello" g.Name = "world" g.LoopMessage = 5 // Call Method 2 g.salute() // Overloaded Method 2.1 and Getters g.salute21(g.Message, "fantom", g.LoopMessage) // Overloaded Method 2.2 g.salute22("carlos") // Stop and exit echo("Press any key to exit...") console := Env.cur userInput := console.in.readLine } }
Greetings Program - Minimal
// Fantom Basics class Greet { // Fields or Attributes private Str? message private Str? name private Int? loopMessage // Properties, Getters and Setters Str Message { get { return &message } set { &message = capitalize(it) } } Str Name { get { return &name } set { &name = capitalize(it) } } Int LoopMessage { get { return &loopMessage } set { &loopMessage = it } } // Constructor new make() { message = "" name = "" loopMessage = 0 } // Overloaded Constructor // No Overloaded Constructor support as designed // Method 1 private Str capitalize(Str val) { // "if-then-else" statement if (val.size >= 1) { return val.capitalize } else { return "" } } // Method 2 Void salute() { // "for" statement for (i:=1; i<=loopMessage; i++) { echo("$message $name!") } } // Overloaded Method // No Overloaded Methods Support in Fantom. News methods instead. // Method 2.1 Void salute21(Str message, Str name, Int loopMessage) { // "while" statement Int i := 0 while(i < loopMessage) { echo("${capitalize(message)} ${capitalize(name)}!") i++ } } // Method 2.2 Void salute22(Str name) { // "switch/case" statement DateTime dtNow := DateTime.now; switch(dtNow.hour) { case 6: case 7: case 8: case 9: case 10: case 11: message = "good morning," case 12: case 13: case 14: case 15: case 16: case 17: message = "good afternoon," case 18: case 19: case 20: case 21: case 22: message = "good evening," case 23: case 0: case 1: case 2: case 3: case 4: case 5: message = "good night," default: message = "huh?" } echo("${capitalize(message)} ${capitalize(name)}!") } } // Console Program class FanGreetProgram { static Void main() { // Define variable object of type Greet and Instantiate. Call Constructor Greet g := Greet() // Call Setters g.Message = "hello" g.Name = "world" g.LoopMessage = 5 // Call Method 2 g.salute // Overloaded Method 2.1 and Getters g.salute21(g.Message, "fantom", g.LoopMessage) // Overloaded Method 2.2 g.salute22("carlos") // Stop and exit echo("Press any key to exit...") console := Env.cur userInput := console.in.readLine } }
And the Output is:
Emulating Overloaded Constructor in Fantom
Fantom does not support Overloading Constructors by design, but you can some how "emulate" it by calling the constructor with an initializers list as shown here below.
class Greet { // defining public fields Str? message Str? name Int? loopMessage // Constructor new make() { echo("greet.make") message = "empty_message" name = "empty_name" loopMessage = 0 } // Method 2 Void Salute() { echo("$this.loopMessage $this.message $this.name!") } } class Program { static Void main() { // calling constructor (printing greet.make) Greet g := Greet() g.Salute() // calling constructor (printing greet.make) and explicitly assigning values to each field // this can be done if the fields are defined as public // or you will get a Private field xxx not accessible Greet g2 := Greet{ message="hello"; name="world"; loopMessage=5 } g2.Salute() } }
And the Output is:
Great example - good to see Fantom getting more exposure!!
ReplyDeleteA couple of suggestions on things that are simpler and IMHO make the example much cleaner (although I appreciate you're trying to show the core functionality across a range of languages and not getting too far into the idioms of each):
Your properties can be rewritten as:
// Slot storage is implicit in the definition, and since they're initialised
// in the constructor, they can be non-nullable (Str not Str?)
Str message {
set { &message = Capitalize(it) }
}
Str name {
set { &name = Capitalize(it) }
}
Int loopMessage
Your capitalize function can be made a bit more succinct:
// Optional () on isEmpty - since it takes no args
private Str Capitalize(Str val) {
if (val.isEmpty) {
return Str.defVal
} else {
return val.capitalize()
}
}
Or if you make the names non-nullable as mentioned above:
// No () on capitalize - again no args, so not needed
// Also no "return" - if there's a single statement,it's optional.
private Str Capitalize(Str val) {
val.capitalize
}
(or just remove completely and inline the calls)
Your Salute() method could be rewritten with Int.times and closure (appreciate you're trying to illustrate the for() loop):
Void Salute() {
loopMessage.times { echo("$message $name!")}
}
Or with Range.each and a closure:
Void Salute() {
(1..loopMessage).each { echo("$message $name!")}
}
Your Salute21 method could also use string interpolation with the Capitalize function:
Void Salute21(Str message, Str name, Int loopMessage) {
Int i := 0
while(i < loopMessage) {
echo("${Capitalize(message)} ${Capitalize(name)}!")
i++
}
}
Also, the method names should start with a lower case letter, not an uppercase one.
ReplyDelete@ M
ReplyDeleteThanks for your comments and code samples M, really appreciated that.
I will update the code examples as suggested. Concerning loops i will show those forms that you are proposing in future posts.
@ JodaStephen,
Thanks for the comment. I will update that as well.