This repository has been archived by the owner on Jul 10, 2018. It is now read-only.
forked from rubinius/rubinius
/
index.html
330 lines (279 loc) · 17.2 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
<!DOCTYPE html>
<html>
<head>
<title>Introduction to Fancy - Rubinius</title>
<meta content='text/html;charset=utf-8' http-equiv='content-type'>
<meta content='en' http-equiv='content-language'>
<meta content='Rubinius is an implementation of the Ruby programming language. The Rubinius bytecode virtual machine is written in C++. The bytecode compiler is written in pure Ruby. The vast majority of the core library is also written in Ruby, with some supporting primitives that interact with the VM directly.' name='description'>
<meta content='Less Than Three. <3. http://less.thanthree.com' name='author'>
<link href='/' rel='home'>
<link href='/' rel='start'>
<link href='/feed/atom.xml' rel='alternate' type='application/atom+xml' title='Rubinius Blog' />
<!--[if IE]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script><![endif]-->
<script src="/javascripts/jquery-1.3.2.js" type="text/javascript"></script>
<script src="/javascripts/paging_keys.js" type="text/javascript"></script>
<script src="/javascripts/application.js" type="text/javascript"></script>
<style>article, aside, dialog, figure, footer, header, hgroup, menu, nav, section { display: block; }</style>
<link href="/stylesheets/blueprint/screen.css" media="screen" rel="stylesheet" type="text/css" />
<link href="/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
<link href="/stylesheets/blueprint/print.css" media="print" rel="stylesheet" type="text/css" />
<!--[if IE]><link href="/stylesheets/blueprint/ie.css" media="screen" rel="stylesheet" type="text/css" /><![endif]-->
<!--[if IE]><link href="/stylesheets/ie.css" media="screen" rel="stylesheet" type="text/css" /><![endif]-->
<link href="/stylesheets/pygments.css" media="screen" rel="stylesheet" type="text/css" />
</head>
<body>
<div class='container'>
<div class='span-21 blog_menu'>
<header>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a id="blog" href="/blog/">Blog</a></li>
<li><a id="documentation" href="/doc/en/">Documentation</a></li>
<li><a href="/projects/">Projects</a></li>
<li><a href="/roadmap/">Roadmap</a></li>
<li><a href="/releases/">Releases</a></li>
</ul>
</nav>
</header>
</div>
<div class='span-3 last'>
<div id='version'>
<a href="/releases/1.2.3">1.2.3</a>
</div>
</div>
</div>
<div class="container posts_nav">
<nav>
<a href="/blog/posts_index/">Index of Posts</a>
<a id="feed_icon" href="/feed/atom.xml"><img alt="subscribe" src="/images/feed-icon16x16.png" /></a>
</nav>
</div>
<div class="container blog_posts">
<h2 class="post_title">Introduction to Fancy</h2>
<div class="by_line">
<p><span class="author">Christopher Bertels</span>
<span class="date">23 February 2011</span>
</p>
</div>
<p>Fancy is a new general-purpose programming language targetting the
Rubinius VM.</p>
<p>This blog post will give a short introduction to the language, what
kind of problems it’s trying to solve and why I chose Rubinius as the
VM to run Fancy on.</p>
<h3 id="what-is-fancy">What is Fancy?</h3>
<p>Fancy is a new general-purpose, dynamic, pure object-oriented
programming language heavily inspired by Ruby, Smalltalk and Erlang
that runs on the Rubinius VM. It’s the first fully bootstrapped
language, aside from Ruby, running on Rubinius. This means that the
compiler that generates bytecode for Rubinius is written in Fancy
itself.</p>
<p>You can think of Fancy as a mix of features from the mentioned
languages above, taking each of their strengths and improving upon
their weaknesses.
Fancy has a very small core and is largely based on the concept of
message passing, just like Smalltalk. It tries to have as many
language concepts being first-class values in the language.</p>
<p>Just like Ruby, Fancy is a dynamic object-oriented language that
allows changing code at runtime, everything being an expression and
generally embracing more then one way to do things. Fancy also has all
the literal support that Ruby has, plus literal syntax for Tuples and
Patterns (more on that below).</p>
<p>In contrast to Ruby and just like Smalltalk, Fancy has a very small
amount of built-in keywords and all of the control structures are
implemented in terms of message sends to objects using closures.</p>
<p>The third language that served as an inspiration is Erlang, from which
Fancy takes the idea that concurrent programming should be easy by
having the Actor Model built into the language. This part is still a
work in progress, but should come together soon. The fact that
Rubinius has a built-in Channel type, inter-VM communication
capabilities and even an actor library makes implementing this easier
than in traditional systems.</p>
<h3 id="why-fancy">Why Fancy?</h3>
<p>I believe there is real value in having a language that supports
certain things out of the box. Especially when it comes to things like
asynchronous and concurrent programming, having proper semantics built
into the language can often help developers more than a library can.
Very often it’s not just about the functionality itself but also about
the semantics you want that functionality to have. This can cause
problems particularly if the language’s semantics differ from what
your library is trying to solve. A good example is the callback-based
approach to asynchronous progamming which leads to code that differs
both in semantics as well as how code is structured, compared to
synchronous code. Ideally you’d still want to write code in a
synchronous fashion, where exceptions pop up naturally while still
being highly asynchronous.</p>
<p>In that sense Fancy is more flexible than Ruby as there’s not many
special case semantics built in to the core language. Everything’s
done via message passing, which fits nicely the actor model approach
to concurrency. Fancy’s syntax is a lot simpler, too.</p>
<p>Since all the core control structures are just implemented in Fancy
itself and adhere to the message passing protocol, you can easily
override them for your personal needs. This is especially interesting
when implementing domain specific languages.
Say, you’d want to add some logging to conditional or looping
constructs - it’s as easy as overriding a method in your DSL’s
classes. Fancy also has class-based mixins, so it makes it easy to
share functionality across class hierarchy boundaries.</p>
<p>Finally, I created Fancy because I wanted a language implementation
that was well documented, easy to understand and very flexible to
extend. Ruby is a nice language, but it has some inconsistencies and
there’s only so much you can do when you’re bound by backwards
compatibility. By starting fresh, Fancy has a clean, simple and easy
to extend core which allows further exploration of features and
abstractions.</p>
<h3 id="why-target-rubinius">Why target Rubinius?</h3>
<p>The initial implementation of Fancy was a simple interpreter written
in C++, similar to how Ruby 1.8 (MRI) works. It was a simple AST
walker. After moving to Rubinius and writing an initial bootstrap
compiler in Ruby, the codebase shrank to about 20% of the original
implementation while actually being more performant. This of course is
mostly due to Rubinius’ architecture and JIT compiler but it was a
great experience nontheless.</p>
<p>The nice part about having a common virtual machine and runtime is
that you’re not forced to a completely different platform to get the
job done. Fancy and Ruby can coexist in the same application nicely
and calling code from one another is dead simple. In fact, as of now,
Rubinius doesn’t know anything about Fancy. And it shouldn’t. As long
as all languages running on top of it adhere to the same interface
(in this case the bytecode), it should just work fine.</p>
<p>Choosing Rubinius as a successor platform for Fancy was easy. It’s
built for Ruby, a language that’s closely related to Fancy. Rubinius,
while having been developed as a VM for running Ruby code, is very
flexible and there are many features that abstract over Ruby’s
external semantics. It was just a natural choice given the fact that
Rubinius’ architecture and design was heavily influenced by Smalltalk
VMs. Also, it’s a very nice dynamic bytecode virtual machine. The
community is very responsive and helpful. Bugs get fixed instantly,
there’s always someone to help out and overall it’s been a great
experience.</p>
<h3 id="lets-look-at-some-code">Let’s look at some code!</h3>
<p>OK, enough talking. Let’s have a look on how to get some Fancy code up
and running. Our little sample application will be a simple IRC bot
that connects to Fancy’s irc channel on Freenode and says hello to
everyone that greets it. To make life easier, there’s already a Fancy
package out there that helps with exactly this task:
<a href="https://github.com/bakkdoor/fancy_irc">FancyIRC</a>.</p>
<p>FancyIRC is a simple IRC client library inspired by Ruby’s IRC bot
framework <a href="https://github.com/cinchrb/cinch">Cinch</a>. It’s much simpler
and the code is fairly easy to read, but it gives you a similar
interface for writing IRC clients or bots.</p>
<p>So let’s get going by installing Fancy. You can either use the Fancy
Rubygem and install it with Rubinius or get the code from GitHub and
run <code>rake</code> in the directory. You’ll also then have to add the <code>bin</code>
directory to your <code>$PATH</code>. If you want the latest and greatest version
of Fancy I recommend building directly from source, as the Gem might
not be up to date all the time. For demonstration purposes, let’s
install the Rubygem.</p>
<pre><code>$ rbx -S gem install fancy
</code></pre>
<p>To get the FancyIRC package we use Fancy’s built-in package manager,
which knows how to find the code on GitHub and install it locally:</p>
<pre><code>$ fancy install bakkdoor/fancy_irc
</code></pre>
<h4 id="writing-the-code">Writing the code</h4>
<div class="highlight"><pre><code class="fancy"><span class="lineno"> 1</span> <span class="nf">require:</span> <span class="s">"fancy_irc"</span>
<span class="lineno"> 2</span>
<span class="lineno"> 3</span> <span class="n">greeter_bot</span> <span class="o">=</span> <span class="no">FancyIRC</span> <span class="no">Client</span> <span class="nf">new:</span> <span class="p">{</span>
<span class="lineno"> 4</span> <span class="nf">configuration:</span> <span class="p">{</span>
<span class="lineno"> 5</span> <span class="nf">nickname:</span> <span class="s">"greeter_bot"</span>
<span class="lineno"> 6</span> <span class="nf">server:</span> <span class="s">"irc.freenode.net"</span>
<span class="lineno"> 7</span> <span class="nf">port:</span> <span class="mi">6667</span>
<span class="lineno"> 8</span> <span class="nf">channels:</span> <span class="o">[</span><span class="s">"#fancy"</span><span class="o">]</span>
<span class="lineno"> 9</span> <span class="p">}</span>
<span class="lineno">10</span>
<span class="lineno">11</span> <span class="c1"># greet person back</span>
<span class="lineno">12</span> <span class="nf">on:</span> <span class="ss">'channel</span> <span class="nf">pattern:</span> <span class="sr">/^[hH]ello greeter_bot/</span> <span class="nf">do:</span> <span class="p">|</span><span class="n">msg</span><span class="p">|</span> <span class="p">{</span>
<span class="lineno">13</span> <span class="n">msg</span> <span class="nf">reply:</span> <span class="s">"Hello to you too, #{msg author}!"</span>
<span class="lineno">14</span> <span class="p">}</span>
<span class="lineno">15</span>
<span class="lineno">16</span> <span class="c1"># "echo" command</span>
<span class="lineno">17</span> <span class="c1"># invoke with: !echo <text></span>
<span class="lineno">18</span> <span class="nf">on:</span> <span class="ss">'channel</span> <span class="nf">pattern:</span> <span class="sr">/^!echo (.*)$/</span> <span class="nf">do:</span> <span class="p">|</span><span class="n">msg</span><span class="p">,</span> <span class="n">text</span><span class="p">|</span> <span class="p">{</span>
<span class="lineno">19</span> <span class="n">msg</span> <span class="nf">reply:</span> <span class="s">"#{msg author} said: #{text}"</span>
<span class="lineno">20</span> <span class="p">}</span>
<span class="lineno">21</span>
<span class="lineno">22</span> <span class="c1"># tell bot to shutdown via !shutdown command</span>
<span class="lineno">23</span> <span class="nf">on:</span> <span class="ss">'channel</span> <span class="nf">pattern:</span> <span class="sr">/^!shutdown/</span> <span class="nf">do:</span> <span class="p">|</span><span class="n">msg</span><span class="p">|</span> <span class="p">{</span>
<span class="lineno">24</span> <span class="n">msg</span> <span class="nf">reply:</span> <span class="s">"OK, shutting down"</span>
<span class="lineno">25</span> <span class="no">System</span> <span class="n">exit</span>
<span class="lineno">26</span> <span class="p">}</span>
<span class="lineno">27</span> <span class="p">}</span>
<span class="lineno">28</span>
<span class="lineno">29</span> <span class="n">greeter_bot</span> <span class="n">connect</span>
<span class="lineno">30</span> <span class="n">greeter_bot</span> <span class="n">run</span>
</code></pre>
</div>
<p>I think the code is pretty straight forward. This should give you a
feeling for what Fancy looks and feels like. There is of course lots
more to Fancy than what was shown here. It would not fit into a single
blog post.</p>
<p>A quick list of what’s currently being worked on:</p>
<ul>
<li>New pattern matching system: Message passing based pattern matching
that preserves encapsulation and is very extensible including
pattern literals that allow custom pattern types to be defined by
anyone. There’s an experimental branch for that. I’m happy
to answer questions.</li>
<li>Async support using coroutines (Fibers) - Write async code in a more
natural way where exceptions propagate naturally and you don’t have
to think about callbacks all the time.</li>
<li>First-class support for actors - Asynchronous message sends, Futures
and multi-vm messaging built-in.</li>
<li>And much more…</li>
</ul>
<h3 id="interested">Interested?</h3>
<p>If you got interested in Fancy and want to know where to go next,
here’s a short list of things to check out:</p>
<ul>
<li><a href="https://github.com/bakkdoor/fancy">Fancy’s GitHub repository</a>.
The standard library is completely written in Fancy and most classes
and methods have docstrings. It should be fairly easy to understand.</li>
<li><a href="https://github.com/fancy-lang/infancy">Programming InFancy</a>
An open source tutorial on learning Fancy. Work in progress.</li>
<li><a href="http://api.fancy-lang.org">http://api.fancy-lang.org</a>
A work in progress page containing Fancy’s standard library class
and method documentation.</li>
<li><a href="https://groups.google.com/forum/#!forum/fancy-lang">Fancy’s Google Group mailinglist</a></li>
<li>IRC Channel: #fancy @ irc.freenode.net</li>
<li>Website: <a href="http://www.fancy-lang.org">http://www.fancy-lang.org</a></li>
</ul>
<div id="disqus_thread"></div>
<script type="text/javascript">
var disqus_shortname = 'rubinius';
var disqus_identifier = '/2011/02/23/introduction-to-fancy/';
var disqus_url = 'http://rubini.us/2011/02/23/introduction-to-fancy/';
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
</div>
<footer>
<div class='container'>
<nav>
<ul>
<li><a href="http://twitter.com/rubinius">Follow Rubinius on Twitter</a></li>
<li><a href="http://github.com/evanphx/rubinius">Fork Rubinius on github</a></li>
<li><a href="http://engineyard.com">An Engine Yard project</a></li>
<li id='credit'>
Site design by
<a href="http://less.thanthree.com">Less Than Three</a>
</li>
</ul>
</nav>
</div>
</footer>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-12328521-1");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>