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 |
//Grace in one page; run here: http://www.cs.pdx.edu/~grace/ import "io" as transput // import module — the imported object is named transput print "Hello World!" // Comments & Layout // comment to end of line // Definitions and Variables def one = 1 // constant def two:Number = 2 // constant with type annotation var i:Number := 13 // variable with type - note := var x := 4 // variable, dynamically typed var z is readable, writable := "Z" // annotated to give public access //Literals 1 16xF00F00 2x10110100 0xdeadbeef // Radix zero treated as 16 true false // Booleans "Hello World!" "fruit\tcost" // string with escape for tab "1 + 2 = {1 + 2}" // string with interpolation {two.something} // block (lambda expression) without parameters { j -> print(j)} // blocks with parameters // Requests self.z // explicit self request, without arguments z // implicit self-request, without arguments print "Hello world" // implicit self-request, single string argument "Hello".size // request of method size with string "Hello" as receiver "abcdefghi".substringFrom 3 to 6 // request of method substringFrom(_)to(_); parens optional on literal arguments 1 + 2 * 3 // operators are also requests ! false // unary prefix operators! Can't do that in Smalltalk. "ab" ++ "cd" // operator ++ for string concatenation 1..10 // operator .. constructs a range of numbers (true || false) && true // only + - * and / have precedence x := 22 // assignment request // Control Structures — block bodies are indented when the // block spans multiple lines if (x == 22) then { print "YES" } elseif { x == 23 } then { print "Maybe" } else { print "...nope..." } for (2 .. 4) do { j -> print(j) } // prints 2, 3, and 4 x := 10 while {x < 20} do { print(x) x := x + 3 } match (x) // match(_)case(_)... can match on both values and types case { 0 -> print "zero" } // literal — matches when x == 0 case { n : Number -> print "Number {n}" } // type matches case { s : String -> print "String {s}" } else { print "who knows?" } // all other cases // Methods // Grace methods can be at the "top level" method pi {3.141592634} //simple method method + (other) { other + self } // binary operator method prefix- {print "bing!"} //prefix unary operator method from(n : Number) steps(s: Number) -> Number { // method with multi-part name, each part with an argument list print "from {n} steps {s}" return s } method fromsteps(n: Number, s: Number) -> Number { // method with multiple arguments print "from {n} steps {s}" return s } // Objects def fergus = object { // make a new object def colour is readable = "Tabby" def name is readable = "Fergus" var miceEaten := 0 method eatMouse {miceEaten := miceEaten + 1} method miaow {print "{name}({colour}) has eaten {miceEaten} mice"} } fergus.eatMouse fergus.eatMouse fergus.miaow // Classes class cat(name') colour(colour') { // class is a factory method def colour is readable = colour' // note primes on names def name is readable = name' var miceEaten := 0 method eatMouse {miceEaten := miceEaten + 1} method miaow { print "{name}({colour}) has eaten {miceEaten} mice" } } cat "Amelia" colour "Tortoiseshell".miaow // Inheritance class pedigreeCat(aName) colour(aColour) { inherit cat(aName) colour("Pedigree " ++ aColour) // call superclass's factory alias catMiaow = miaow var prizes := 0 // initialize an instance variable method winner {prizes := prizes + 1} method miaow is override { catMiaow print "and won {prizes} prizes" } } def woopert = pedigreeCat "Woopert" colour "Siamese" woopert.winner woopert.winner woopert.winner woopert.miaow // Exceptions def NegativeError = ProgrammingError.refine "NegativeError" // make a new kind of exception try { ... // some complicated code NegativeError.raise "-1 < 0" // raise (throw) an exception } catch { ne: NegativeError -> print "it was negative! {ne}" } catch { e: Exception -> print "an unexpected exception {e}" } finally { print "finally!" // always executed } // using a module transput.output.write "Goodbye\n" // request method on imported module |
Changed 27 June 2014 to reflect renaming from “catch()case()..” to “try()catch())…”
Changed 7 May 2015 to avoid lambda bound variable shadowing “var i”
Changed 27 Nov 2015 to move to kernan. This will no longer run in minigrace.
There is also an older minigrace version
Where can one download the compiler and tools for the grace language?
Hi Fred.
Implementations of Grace (such as they are) are here: http://gracelang.org/applications/grace-versions/
Kernan is probably the best for experimenting, while people are teaching with Minigrace.
Changed 9 April 2016 to move towards spec. This will no longer run anywhere.