├── README.md
├── Chapter04.md
├── Chapter03.md
├── Chapter02.md
└── Chapter01.md
/README.md:
--------------------------------------------------------------------------------
1 | # Programming InFancy #
2 | ## An OpenSource Book to teach the Fancy Programming Language. ##
3 |
4 | This is a work-in-progress book for learning the Fancy Programming
5 | Language.
6 | Each chapter is in its own .md file, starting with [Chapter01.md][] which
7 | gives a short introduction into Fancy's basic concepts and ideas.
8 |
9 | # [Start reading →][Chapter01.md]
10 |
11 | [Chapter01.md]: Chapter01.md
12 |
--------------------------------------------------------------------------------
/Chapter04.md:
--------------------------------------------------------------------------------
1 | # Chapter 04 #
2 |
3 | ## 4.1 More Blocks ##
4 |
5 | Blocks play a vital role in Fancy. They're used for many different
6 | things that all have one thing in common: Allow seperation of concerns
7 | in a natural way and providing the possibility to write code close to
8 | your problem domain. This means writing DSLs in Fancy is a natural and
9 | easy thing to do, due to the keyword-based message syntax.
10 |
11 | ## 4.2 Partial Blocks ##
12 |
13 | Fancy has the concept of Partial Blocks.
14 | Partial Blocks behave like regular Blocks but have their argument
15 | ommitted. They always only take one argument which is implicit and
16 | that argument gets prefixed into any message send within the Block as
17 | its receiver. They allow Ruby-style simple DSLs while not relying on
18 | `instance_eval`, as many Ruby DSLs do, thus preserving things like the
19 | binding of self within the Block. Examples for libraries using
20 | `instance_eval` heavily are Sinatra and parts of Ruby on Rails.
21 |
22 | One good example is Fancy's built-in
23 | [HTML Generator Class](https://github.com/bakkdoor/fancy/blob/master/lib/html.fy)
24 | which can be used for writing Webapps, for example. I wrote a simple
25 | url-shortener webapp with Sinatra for Fancy. See
26 | [here](https://github.com/bakkdoor/shortefy).
27 | You'll also find a link to a Screencast there.
28 |
29 | Let's have a look at what I mean.
30 |
31 | ### 4.2.1 Without Partial Blocks ###
32 |
33 | ```fancy
34 | require: "html"
35 |
36 | html = HTML new: |h| {
37 | h html: |h| {
38 | h head: |h| {
39 | h title: "Using HTML Class"
40 | }
41 | h body: |h| {
42 | h div: { id: "header" } with: |h| {
43 | h h1: { class: "title" } with: "My Title"
44 | }
45 | h div: { id: "footer" } with: |h| {
46 | h h3: "The End."
47 | }
48 | }
49 | }
50 | }
51 | ```
52 |
53 | ### 4.2.2 And the same code with Partial Blocks ###
54 |
55 | ```fancy
56 | require: "html"
57 |
58 | html2 = HTML new: @{
59 | html: @{
60 | head: @{
61 | title: "Using HTML Class"
62 | }
63 | body: @{
64 | div: { id: "header" } with: @{
65 | h1: { class: "title" } with: "My Title"
66 | }
67 | div: { id: "footer" } with: @{
68 | h3: "The End."
69 | }
70 | }
71 | }
72 | }
73 | ```
74 |
75 | Both code snippets will produce this output:
76 |
77 | ```html
78 |
79 |
80 |
81 | Using HTML Class
82 |
83 |
84 |
85 |
90 |
95 |
96 |
97 | ```
98 |
99 | Since Partial Blocks preserve the meaning of self, you can use the
100 | HTML generator class for your view code and don't need to use a
101 | seperate template language, as all instance variables will be bound
102 | nicely, depending on where you put that code.
--------------------------------------------------------------------------------
/Chapter03.md:
--------------------------------------------------------------------------------
1 | # Chapter 03 #
2 |
3 | ## 3.1 Numbers ##
4 |
5 | As any programming language, Fancy has number literal syntax built in.
6 |
7 | ### 3.1.1 Integers (Fixnums) ###
8 |
9 | There are multiple ways to write a `Fixnum` (Integer value). Here's a list of possible ways to write a `Fixnum`:
10 |
11 | * `1`, `123`, `1_000_000`, `999_888_777` etc. Underscores are ignored and used purely to be easier to read (especially large numbers)
12 | * Binary literals: `0b10101`, `0B01010101111`
13 | * Hexadecimal literals: `0xff`, `0xAB`, `0XAF`
14 | * Octal literals: `0o77`, `0O13`
15 |
16 | ### 3.1.2 Floats ###
17 |
18 | Floats only allow one way of writing them: `10.9997`, `0.123`, `1.0`
19 |
20 | **Note:** Both Fixnums and Floats can be prefixed with a `-` for negative numbers.
21 |
22 |
23 | ## 3.2 Strings ##
24 |
25 | Strings are what you expect them to be.
26 |
27 | Examples:
28 |
29 | ```fancy
30 | "Hello, World"
31 | "Hello,\n World"
32 |
33 | """
34 | This is a multi-line String
35 | The newlines become part of the String and start and end with a triple quote,
36 | just as in Python. They're most commonly used for docstrings, which we'll talk about
37 | later (also copied from Python).
38 | """
39 | ```
40 |
41 | Fancy also has support for Ruby-like string interpolation:
42 |
43 | ```fancy
44 | "This is a String with a value interpolated: 3 ** 3 = #{3 ** 3}"
45 | "Hello, #{name}, I'm #{age} years old."
46 | ```
47 |
48 | ## 3.3 Symbols ##
49 |
50 | Symbols are unique identifiers. They're equivalent to Ruby's Symbols.
51 |
52 | Examples:
53 |
54 | ```fancy
55 | 'foo
56 | 'foo?
57 | 'foo:bar:
58 | 'foo_bar!?Baz!?!
59 | 'helloWorld
60 | 'hello123!?=*
61 | ```
62 |
63 |
64 | ## 3.4 Tuples ##
65 |
66 | In contrast to Ruby and like Python, Fancy has built-in literal syntax for Tuples. Tuples are constant-sized containers with index-based access to members.
67 |
68 | Examples:
69 |
70 | ```fancy
71 | (1, 2) # Tuple with values 1 and 2
72 | (1, 2, "foo")
73 | ('foo, 'bar, "baz!")
74 | (1, (2, 3), (4, (5, 6, 7))) # nested Tuples
75 |
76 | # Accessing elements:
77 | (1, 2, 3) at: 2 # => 3
78 | (1, 2, 3)[0] # => 1
79 | ```
80 |
81 |
82 | ## 3.5 Arrays ##
83 |
84 | One of the most used data structure are arrays. In Fancy there's the `Array` class which provides index-based constant time access to dynamically resizable (growing) polymorphic containers.
85 | Let's have a look at some `Array` examples:
86 |
87 | ```fancy
88 | # An Array containing 5 integers (Fixnums)
89 | [1,2,3,4,5]
90 |
91 | # An Array of 2 numbers, 1 String and another Array
92 | [1, 2, "An Array!", [4,5, "Yes, indeed!"]]
93 | ```
94 |
95 | Arrays work the same way as they do, for example, in Ruby. In Fact, they're sharing the same Class as their Ruby equivalents. Anytime you're using a Fancy Array, you're also using a Ruby Array inside Rubinius. There is no wrapper in between. This is true not only for Arrays, but for all built-in types and classes where there is a Ruby equivalent available.
96 |
97 |
98 | ## 3.6 Hashes (Dictionaries, Hashmaps) ##
99 |
100 | Hashes are unordered collections of key-value pairs with fast access through keys. They can nest arbitrarily, just as Arrays.
101 |
102 | Examples:
103 |
104 | ```fancy
105 | <['name => "Fancy", 'type => "Programming Language", 'created => 2010]>
106 | ```
107 |
108 | You can of course use any other type besides Symbols as keys and values.
109 |
110 |
111 | ## 3.7 Blocks (BlockEnvironment, Closures) ##
112 |
113 | One of the most heavily used literal values in Fancy are Blocks. They're used to implement nearly all control structures (like traditional `if`, `else`, `while` etc constructs) and are proper closures with interesting `return` semantics.
114 |
115 | We've seen Blocks in Chapter 1 before, but for completeness, here's a list of some literal Blocks:
116 |
117 | ```fancy
118 | { "A Block with no argument" println }
119 | |x| { "A Block with one argument, value: #{x}" println }
120 | |x y| { "A Block with two arguments, values: #{x} and #{y}" println }
121 |
122 | # Seperating arguments with comma is optional, thus this is valid as well:
123 | |x, y| { "The sum is: #{x + y}" println }
124 | ```
125 |
126 | There's also *Partial Blocks* which can be used for Blocks only taking
127 | one argument:
128 |
129 | ```fancy
130 | @{ + 1 } # is the same as: |x| { x + 1 }
131 | # e.g.:
132 | [1,2,3,4] map: @{+ 1} # => [2,3,4,5]
133 | ```
134 |
135 | To `call` a Block, you send it the `call` or `call:` message and pass the arguments in as an Array:
136 |
137 | ```fancy
138 | block = |x, y| { x + y println }
139 | block call: [2, 3] # will print 5
140 | ```
141 |
142 |
143 | ## 3.8 Regular Expressions ##
144 |
145 | Fancy, as Ruby or Perl, has Regular Expressions built-in to the
146 | language. In fact, it uses the same implementation that Ruby uses on
147 | top of Rubinius, including the same literal syntax:
148 |
149 | ```fancy
150 | /^Hello, (.*)!$/
151 | /^[A-Z][a-Z0-9_:]$/
152 | ```
153 |
154 |
155 | ## 3.9 Ranges ##
156 |
157 | Fancy also has Ranges, like Ruby:
158 |
159 | ```fancy
160 | (1..10)
161 | (a..b)
162 | (x .. x ** x)
163 | ```
164 |
165 | #### [Chapter 4][Chapter 4] will deal with one of Fancy's central features, namely Blocks, some more. ####
166 |
167 | [Chapter 4]: Chapter04.md
168 |
--------------------------------------------------------------------------------
/Chapter02.md:
--------------------------------------------------------------------------------
1 | # Chapter 02 #
2 |
3 | ## 2.1 Class Definitions ##
4 |
5 | Classes in Fancy are first-class values (they are instances of the
6 | `Class` class, just as in Ruby or Smalltalk).
7 |
8 | There's several ways to define Classes in Fancy, but the common one is
9 | to use the built-in syntax for it. Compared to Smalltalk, where class
10 | definitions are just message sends as well, Fancy also provides syntax
11 | for doing so, just as Ruby and most other object-oriented programming
12 | languages out there.
13 |
14 | ```fancy
15 | class Person {
16 | }
17 | ```
18 |
19 | Defines an empty class called `Person` which implicitly inherits from
20 | `Object`, the root class of Fancy's class hierarchy.
21 |
22 | To define a class that inherits from another class we specify the
23 | super class after a colon, like so:
24 |
25 | ```fancy
26 | class ImaginaryPerson : Person {
27 | # Person is the super class of ImaginaryPerson
28 | # ...
29 | }
30 | ```
31 |
32 |
33 | ## 2.2 Method definitions ##
34 |
35 | Let's define a `name` method for `Person` which returns a `String`
36 | representing the name of a `Person` (for now we'll just use the same
37 | name for all instances of `Person`):
38 |
39 | ```fancy
40 | class Person {
41 | def name {
42 | "John Doe"
43 | }
44 | }
45 | ```
46 |
47 | If we create a new `Person` now and send it the `name` message, we'll
48 | get "John Doe" as a response:
49 |
50 | ```fancy
51 | p = Person new
52 | p name # => "John Doe"
53 | ```
54 |
55 |
56 | ### 2.2.1 Constructor method ###
57 |
58 | Let's refactor this code a little and define a constructor that takes
59 | a name and returns that when sent the `name` message:
60 |
61 | ```fancy
62 | class Person {
63 | def initialize: name {
64 | @name = name
65 | }
66 |
67 | def name {
68 | @name
69 | }
70 | }
71 | ```
72 |
73 | As you can see, constructor methods *start* with `initialize`. In our
74 | case the constructor method just takes one argument, a name, and
75 | stores it into the *instance variable* `@name`. Instance variables
76 | start with `@` and *class variables* start with `@@`, just as in Ruby.
77 |
78 | Now we can create persons and pass in their names:
79 |
80 | ```fancy
81 | john = Person new: "John Doe"
82 | betty = Person new: "Betty Boop"
83 | john name # => "John Doe"
84 | betty name # => "Betty Boop"
85 | ```
86 |
87 | Constructor methods like `initialize:` are just normal instance
88 | methods, like `name`. They're called with the appropriate arguments
89 | when calling the `Class##new:` class method. For constructors with
90 | multiple arguments, the necessary class constructor methods are
91 | created for you implicitly. Let me show you what I mean:
92 |
93 | ```fancy
94 | class Person {
95 | def initialize: name age: age city: city {
96 | @name = name
97 | @age = age
98 | @city = city
99 | }
100 |
101 | def name {
102 | @name
103 | }
104 |
105 | def age {
106 | @age
107 | }
108 |
109 | def city {
110 | @city
111 | }
112 | }
113 |
114 | p = Person new: "John Doe" age: 42 city: "New York"
115 | p name # => "John Doe"
116 | p age # => 42
117 | p city # => "New York"
118 | ```
119 |
120 | When defining a method starting with `initialize:` it will create a
121 | corresponding class method replacing `initialize:` with `new:` and
122 | keeping the rest of the name. E.g. for an instance method called
123 | `initialize:age:city:` a class method `new:age:city:` is defined which
124 | passes all the arguments on to the `initialize` method.
125 |
126 | ### 2.2.2 Slot readers & writers ###
127 |
128 | There's a simpler way to define so-called *getter-* and
129 | *setter-methods* in Fancy:
130 |
131 | ```fancy
132 | class Person {
133 | # define getter-methods:
134 | read_slots: ['name, 'age, 'city]
135 |
136 | # or if, you'd want them all to be writable:
137 | write_slots: ['name, 'age, 'city]
138 |
139 | # or define both getter & setter methods:
140 | read_write_slots: ['name, 'age, 'city]
141 | }
142 | ```
143 |
144 | We usually refer to *instance variables* as ***slots*** within
145 | Fancy. It's just a different name, but they refer to the exact same
146 | thing.
147 |
148 | `read_slots:` defines reader methods for all the slotnames within a
149 | given Array. `write_slots:` defines setter methods for the slotnames
150 | in a given Array. `read_write_slots:` does both at once. These methods
151 | are completely defined in Fancy and can be found in the `Class` class
152 | definition in Fancy's standard library.
153 |
154 | ### 2.2.3 More syntactic sugar ###
155 |
156 | OK, let's have a look at some more nice syntactic features Fancy
157 | provides for common idioms in method definitions.
158 | First, let's have a look at all the code for the `Person` class we've
159 | written so far. We'll modify it a little to have multiple constructor
160 | methods to emulate default arguments for the missing arguments:
161 |
162 | ```fancy
163 | class Person {
164 | def initialize: name {
165 | initialize: name age: 42 # default is 42
166 | }
167 |
168 | def initialize: name age: age {
169 | initialize: name age: age city: "New York" # default is "New York"
170 | }
171 |
172 | def initialize: name age: age city: city {
173 | @name = name
174 | @age = age
175 | @city = city
176 | }
177 |
178 | # slot readers
179 |
180 | def name {
181 | @name
182 | }
183 |
184 | def age {
185 | @age
186 | }
187 |
188 | def city {
189 | @city
190 | }
191 |
192 | # let's also define slot writer methods:
193 |
194 | def name: new_name {
195 | @name = new_name
196 | }
197 |
198 | def age: new_age {
199 | @age = new_age
200 | }
201 |
202 | def city: new_city {
203 | @city = new_city
204 | }
205 | }
206 | ```
207 |
208 | OK, and now let's define the same stuff with some standard helper
209 | methods and syntax sugar:
210 |
211 | ```fancy
212 | class Person {
213 | read_write_slots: ['name, 'age, 'city]
214 |
215 | def initialize: @name age: @age (42) city: @city ("New York") {
216 | }
217 | }
218 | ```
219 |
220 | Yup, that's it. =)
221 | What's happening here is we're defining getter & setter methods for
222 | the slots `@name, @age` and `@city` and use Fancy's auto slot assignment
223 | syntax in the constructor method, which sets the slot with the given
224 | name to the value passed in as the argument. Finally, we're also using
225 | default argument values (any expression within `(` and `)`). Note,
226 | that you're allowed to refer to arguments passed in further left as
227 | default arguments further right.
228 |
229 | For example:
230 |
231 | ```fancy
232 | def hello: name1 and: name2 (name1) {
233 | "Hello, #{name1} and #{name2}!" println
234 | }
235 |
236 | # call with both arguments:
237 | hello: "Robert" and: "Meggie" # prints "Hello, Robert and Meggie!"
238 |
239 | # call with one argument:
240 | hello: "Max" # prints "Hello, Max and Max!"
241 | ```
242 |
243 |
244 | #### The [next chapter][Chapter 3] will introduce some built-in classes with literal support commonly used in the language. ####
245 |
246 | [Chapter 3]: Chapter03.md
247 |
--------------------------------------------------------------------------------
/Chapter01.md:
--------------------------------------------------------------------------------
1 | # Chapter 01 #
2 | ## 1.1 What is Fancy ? ##
3 |
4 | Fancy is a dynamic, concurrent, pure object-oriented general purpose
5 | programming language inspired by
6 | [Smalltalk](http://en.wikipedia.org/wiki/Smalltalk),
7 | [Ruby](http://en.wikipedia.org/wiki/Ruby_programming_language), and
8 | [Erlang](http://en.wikipedia.org/wiki/Erlang_programming_language).
9 | It runs on [Rubinius](http://www.rubini.us).
10 |
11 | The goal is to create a language implementation that is easy to
12 | understand and improve, even for people new to implementing
13 | programming languages.
14 |
15 | Fancy is a self-hosted language. That means, its compiler is written
16 | in Fancy itself. Apart from the compiler, Fancy's standard library is
17 | mostly written in Fancy, too. The standard library is a good starting
18 | point if you want to get a better feel for the language and its
19 | built-in classes and methods, once you've mastered the fundamental
20 | semantics and syntax.
21 | You can view the standard library classes on GitHub
22 | [here](https://github.com/bakkdoor/fancy/blob/master/lib/).
23 |
24 | OK, enough said, let's get started with Fancy's basic concepts.
25 |
26 |
27 | ## 1.2 Basic concepts ##
28 |
29 | Fancy is heavily inspired by
30 | [Smalltalk](http://en.wikipedia.org/wiki/Smalltalk), a pure
31 | object-oriented,
32 | [message passing](http://en.wikipedia.org/wiki/Message_passing)
33 | dynamic programming language, developed at
34 | [XEROX PARC](http://www.parc.com/) in the 1970s and 1980s.
35 |
36 | The core idea of Smalltalk (and thus Fancy) is the concept of
37 | **message sending** (also called
38 | [*message passing*](http://en.wikipedia.org/wiki/Message_passing)). Fancy
39 | code interacts by sending messages to objects and getting responses
40 | while doing so. You can think of methods as message handlers for
41 | incoming messages on objects. In Fancy, as in Smalltalk and Ruby,
42 | every value is an Object. There is no distinction between so-called
43 | *value types* (or *primitive types*) and *reference types*.
44 |
45 |
46 | ### 1.2.1 Message Sends ###
47 |
48 | In Fancy nearly all operations are done via *message sends*. While
49 | Fancy does have syntax for class & method definitions, importing files
50 | and so on, most of them are just syntactic sugar for equivalent message
51 | sends to objects.
52 |
53 | Let's have a look at how this looks syntactically.
54 |
55 | **No arguments:**
56 |
57 | ```fancy
58 | object message_name
59 | ```
60 |
61 | **Single argument:**
62 |
63 | ```fancy
64 | object message_name: arg
65 | ```
66 |
67 | Is a message send to `object` with a message called `message_name:`
68 | and an argument `arg`. As in Smalltalk (or Objective-C, which is
69 | inspired by Smalltalk), messages are keyword-based and so are
70 | methods. So, if you have multiple arguments in a message send, each
71 | argument is preceeded by a keyword (usually describing the argument).
72 |
73 | **Multiple arguments:**
74 |
75 | ```fancy
76 | object foo: arg1 bar: arg2 baz: arg3
77 | ```
78 |
79 | The above shows a message send with three arguments for the
80 | `foo:bar:baz:` message. If `object`, its class or any superclass
81 | defines a method with the same name, it will get executed with the
82 | given arguments. If not, it will look for a method called
83 | `unknown_message:with_params:` within `object`s inheritance chain (as with
84 | Ruby's `method_missing`).
85 |
86 | Lets look at a more real-world example:
87 |
88 | ```fancy
89 | [1,2,3] each: |x| {
90 | x println
91 | }
92 | ```
93 |
94 | This piece of code shows a message send to a literal Array consisting
95 | of the three number values **1**, **2** and **3**. The `each:` method
96 | expects a **Block** object (or actually, something *callable* - it needs
97 | to implement the `call` and `call:` methods). It will `call:` the
98 | argument given to it with each element in the Array.
99 |
100 | The `|x| { x println }` thing is a Block literal. Blocks are just
101 | normal objects but with built-in syntax (like strings, numbers and
102 | many more). As in Ruby, anything between the pipes (`||`) are arguments
103 | to the block and the code between the curly braces is the body of the
104 | block. Blocks are used as *anonymous methods* (also called *lambda
105 | functions*) and *closures* within Fancy. They are first-class values
106 | in the language, like any other object, and can be passed around to
107 | any method. In Fancy all control structures are implemented with
108 | blocks. But we'll get to that in a minute.
109 |
110 | First off, let's fully explain that code above. As mentioned, the
111 | `each:` method takes something that implements `call:` and passes it
112 | each element in the array in turn. You can think of `each:` being used
113 | as an **iterator**. In terms of the language, `each:` is just a method
114 | like any other though.
115 |
116 | The `println` send to `x` causes it to be displayed on
117 | `*stdout*`. Here's the implementation of `println`:
118 |
119 | ```fancy
120 | def println {
121 | # *stdout* is a dynamic variable
122 | # we'll discuss these later in detail
123 | *stdout* println: to_s
124 | }
125 | ```
126 |
127 | You can find the code in *lib/object.fy* within Fancy's root source
128 | directory or just
129 | [click here](https://github.com/bakkdoor/fancy/blob/master/lib/object.fy#L29)
130 | to view it on Github.
131 |
132 |
133 | ### 1.2.2 Control Structures ###
134 |
135 | As mentioned before, Fancy hardly has any built-in control structures
136 | in contrast to most other programming languages out there. It's
137 | directly inspired by Smalltalk here in that all the usually built-in
138 | control flow structures are implemented with *Blocks* and their
139 | ability to *access variables outside of their scope (and preserve
140 | them)*.
141 |
142 | Let's look at the most common control structures found in other
143 | programming languages.
144 |
145 |
146 | **If/Else:**
147 |
148 | ```fancy
149 | x < y if_true: {
150 | "x is smaller than y" println
151 | } else: {
152 | "x is NOT smaller than y" println
153 | }
154 | ```
155 |
156 | The `else:` part can be ommited, as there's also a method `if_true:`
157 | defined apart from `if_true:else:`. You can also write it the
158 | following (although longer) way:
159 |
160 | ```fancy
161 | if: (x < y) then: {
162 | "x is smaller than y" println
163 | } else: {
164 | "x is NOT smaller than y" println
165 | }
166 |
167 | # there's also this additional way of doing something conditionally:
168 |
169 | { "x is smaller than y" println } if: (x < y)
170 | ```
171 |
172 |
173 | **While:**
174 |
175 | ```fancy
176 | x = 0
177 | { x < 10 } while_true: {
178 | x println
179 | x = x + 1
180 | }
181 |
182 | # or:
183 |
184 | x = 0
185 | while: { x < 10 } do: {
186 | x println
187 | x = x + 1
188 | }
189 | ```
190 |
191 |
192 | **Endless loop:**
193 |
194 | ```fancy
195 | loop: {
196 | # do something here and possibly return when done
197 | }
198 | ```
199 |
200 | **For-loop:**
201 |
202 | ```fancy
203 | 10 times: |i| {
204 | i println # will print 0 - 9
205 | }
206 |
207 | # or:
208 |
209 | 0 upto: 9 do: |i| {
210 | i println # same here.
211 | }
212 | ```
213 |
214 |
215 | #### In [Chapter 2][], we'll have a look how class & method definitions work in Fancy. ####
216 |
217 | [Chapter 2]: Chapter02.md
218 |
--------------------------------------------------------------------------------