<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5564756944652168330</id><updated>2026-04-08T08:22:49.920-04:00</updated><category term="programming"/><category term="REBOL"/><category term="dsl"/><category term="Bindology"/><category term="JavaScript"/><category term="blogging"/><category term="conlang"/><category term="constraints"/><category term="databases"/><category term="rails"/><category term="ruby"/><title type='text'>Loudly Recursive</title><subtitle type='html'>tech thoughts and other nerdery</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.revolucent.net/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://blog.revolucent.net/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Gregory Higley</name><uri>http://www.blogger.com/profile/01615990128586180796</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5564756944652168330.post-8401479814839378753</id><published>2010-08-29T00:17:00.004-04:00</published><updated>2010-08-30T15:30:34.696-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="conlang"/><category scheme="http://www.blogger.com/atom/ns#" term="dsl"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="REBOL"/><title type='text'>A REBOL Dialect For Constructed Languages</title><content type='html'>&lt;p&gt;
 I have had a fascination for languages ever since I read Tolkien and discovered that he had created the Elvish languages from scratch.
 It was this hobby of &amp;ldquo;&lt;a href=&quot;http://en.wikipedia.org/wiki/Conlang&quot;&gt;conlang&lt;/a&gt;&amp;rdquo; design that ultimately led me to become
 a programmer.
&lt;/p&gt;
&lt;p&gt;
 My first programs (written in line-oriented &lt;a href=&quot;http://en.wikipedia.org/wiki/GW_BASIC&quot;&gt;GW-BASIC&lt;/a&gt;) were intended to generate
 random words according to specific rules. I would then pick the most interesting ones for inclusion in whatever language it was
 I was designing at the time. Each program was language-specific. That is, I would choose a set of &lt;a href=&quot;http://en.wikipedia.org/wiki/Phoneme&quot;&gt;phonemes&lt;/a&gt;, 
 create a set of rules for their combination, develop an &lt;a href=&quot;http://en.wikipedia.org/wiki/Orthography&quot;&gt;orthography&lt;/a&gt;, and then write a program to generate 
 valid words.
&lt;/p&gt;
&lt;p&gt;
 When I discovered REBOL, I realized that its dialecting capabilities would be perfect for this task, but instead of having to create a program per language, or
 struggle with other less-than-ideal techniques such as XML configuration files, I could simply create a REBOL dialect to describe the task.
&lt;/p&gt;
&lt;p&gt;
 To illustrate my Conlang Dialect, we&amp;lsquo;ll go through the process of creating a brutally simple language. Obviously we won&amp;rsquo;t bother with grammar and syntax.
 We are dealing just with the sounds. We will call this simple language &lt;i&gt;Na&lt;/i&gt;. Na has only four consonants, &lt;span class=&quot;pre&quot;&gt;s k t n&lt;/span&gt;, and three vowels,
 &lt;span class=&quot;pre&quot;&gt;a i u&lt;/span&gt;. The consonants are as one would expect, and the vowels are pronounced more or less as in Spanish.
&lt;/p&gt;
&lt;p&gt;
 A syllable in Na must always end with a vowel, and must begin with at least one and at most two consonants. Thus &lt;span class=&quot;pre&quot;&gt;a&lt;/span&gt; is not a valid syllable in Na,
 but &lt;span class=&quot;pre&quot;&gt;ta&lt;/span&gt; and &lt;span class=&quot;pre&quot;&gt;tki&lt;/span&gt; are. Words can consist of any number of syllables, but we will stick with those between two and five.
&lt;/p&gt;
&lt;p&gt;
 The Conlang Dialect consists of three verbs, &lt;span class=&quot;pre&quot;&gt;rand&lt;/span&gt;, &lt;span class=&quot;pre&quot;&gt;rept&lt;/span&gt; and &lt;span class=&quot;pre&quot;&gt;join&lt;/span&gt;. Verbs are followed by one
 or more arguments. Our first verb, &lt;span class=&quot;pre&quot;&gt;rand&lt;/span&gt;, can be followed either by a string or a by a REBOL block in a specific format. When followed by a string,
 &lt;span class=&quot;pre&quot;&gt;rand&lt;/span&gt; instructs the Conlang Dialect to randomly choose one of the characters from the string.
&lt;/p&gt;
&lt;pre&gt;rand &quot;aiu&quot;&lt;/pre&gt;
&lt;p&gt;
 When the expression above is evaluated in the Conlang Dialect, it will result either in &quot;a&quot;, &quot;i&quot;, or &quot;u&quot;. However, sometimes we want to say that one choice can occur more
 frequently than other choices. In the Na language, &quot;a&quot; is more common than either &quot;i&quot; or &quot;u&quot;, which are about equally common. We can express this as follows.
&lt;/p&gt;
&lt;pre&gt;rand [
 3 &quot;a&quot;
 1 rand &quot;iu&quot;
]&lt;/pre&gt;
&lt;p&gt;
 This means that 3 out of 4 times, the evaluation of the whole statement will result in &quot;a&quot;, otherwise it will result in the evaluation of the expression
 &lt;span class=&quot;pre&quot;&gt;rand &quot;iu&quot;&lt;/span&gt;. Thus, Conlang Dialect expression can be nested within each other, and often are.
&lt;/p&gt;
&lt;p&gt;
 Now that we have a way to randomly choose strings, we need a way to stitch them together. This is performed by the &lt;span class=&quot;pre&quot;&gt;join&lt;/span&gt; verb, which takes
 a block containing the expressions we want to join.
&lt;/p&gt;
&lt;pre&gt;join [
 rand &quot;sktn&quot;
 rand [
  3 &quot;a&quot;
  1 rand &quot;iu&quot;
 ]
]&lt;/pre&gt;
&lt;p&gt;
 This instructs the Conlang Dialect to take the result of the two expressions inside of the block and combine them. So, for instance, we could get results like &quot;ki&quot;
 and &quot;su&quot; from the whole expression above.
&lt;/p&gt;
&lt;p&gt;
 The last verb in our repertoire is &lt;span class=&quot;pre&quot;&gt;rept&lt;/span&gt;. This verb takes three arguments, and is best illustrated with an example.
&lt;/p&gt;
&lt;pre&gt;rept 1 3 join [
 rand &quot;sktn&quot;
 rand [
  3 &quot;a&quot;
  1 rand &quot;iu&quot;
 ]
]&lt;/pre&gt;
&lt;p&gt;
 The first two arguments of &lt;span class=&quot;pre&quot;&gt;rept&lt;/span&gt; tell the Conlang Dialect to repeat the evaluation of the expression given in the third argument from one
 to three times, in this case. In other words, pick a random number between 1 and 3 and execute the &lt;span class=&quot;pre&quot;&gt;join&lt;/span&gt; expression that number of times,
 stitching the result together. The result of this expression could be words such as &quot;ka&quot;, &quot;kasiki&quot;, &quot;sita&quot;, and so on.
&lt;/p&gt;
&lt;p&gt;
 This is all we need to create the Conlang Dialect, but unfortunately it has some drawbacks. It would be nice if we could assign expressions to names and reuse them,
 and so we can:
&lt;/p&gt;
&lt;pre&gt;na: [
 consonant: rand &quot;sktn&quot;
 onset: rand [
  3 consonant
  1 join [
   consonant
   consonant
  ]
 ]
 vowel: rand [
  3 &quot;a&quot;
  1 rand &quot;iu&quot;
 ]
 syllable: join [onset vowel]
 main: rept 1 5 syllable
]&lt;/pre&gt;
&lt;p&gt;
 Here we have a full specification written in the Conlang Dialect. Expressions are assigned to names using a standard REBOL set-word. It should be fairly obvious from
 the above example how they are used. Assigning expressions in this way is not required, with one exception: The &lt;span class=&quot;pre&quot;&gt;main&lt;/span&gt; expression is required,
 as it serves as the entry point into the specification. Using named expressions makes the Conlang Dialect much more usable, so I highly encourage their use.
&lt;/p&gt;
&lt;p&gt;
 Each verb has a much shorter synonym, and I tend to use these exclusively.
&lt;/p&gt;
&lt;table class=&quot;pre&quot;&gt;
 &lt;tr&gt;
  &lt;td&gt;rand&lt;/td&gt;&lt;td&gt;?&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;rept&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;join&lt;/td&gt;&lt;td&gt;&amp;amp;&lt;/td&gt;
 &lt;/tr&gt; 
&lt;/table&gt;
&lt;p&gt;
 Here is a full program using the Conlang Dialect to produce words in our imaginary Na language. This uses the abbreviated synonyms given above.
&lt;/p&gt;
&lt;pre&gt;REBOL [
 needs: [
  2.100.99.2.5
  http://r3.revolucent.net/net.revolucent.conlang.v1.r 1.0.2
 ]
 license: &#39;mit
]

na: [
 consonant: ? &quot;sktn&quot;
 onset: ? [
  3 consonant
  &amp;amp; [
   consonant
   consonant
  ]
 ]
 vowel: ? [
  3 &quot;a&quot;
  ? &quot;iu&quot;
 ]
 syllable: &amp;amp; [onset vowel]
 main: * 1 5 syllable
]

random/seed now
generator: parse-conlang na
words: []
while [greater? 10 length? words] [
 unless find words word: generator/eval [
  append words word
 ]
]
print words&lt;/pre&gt;
&lt;p&gt;
 And here is a list of ten words generated by executing the program. Of course, subsequent executions are almost certain to produce a different set of words.
&lt;/p&gt;
&lt;pre&gt;nkasanatana
ntusnana
sata
sanuna
kasakukana
skannatu
suknakaka
naka
natasasa
kanika&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.revolucent.net/feeds/8401479814839378753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.revolucent.net/2010/08/rebol-dialect-for-constructed-languages.html#comment-form' title='48 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/8401479814839378753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/8401479814839378753'/><link rel='alternate' type='text/html' href='http://blog.revolucent.net/2010/08/rebol-dialect-for-constructed-languages.html' title='A REBOL Dialect For Constructed Languages'/><author><name>Gregory Higley</name><uri>http://www.blogger.com/profile/01615990128586180796</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>48</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5564756944652168330.post-5262029759364635407</id><published>2009-10-02T12:42:00.006-04:00</published><updated>2009-10-02T13:07:09.248-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="REBOL"/><title type='text'>REBOL Module Names</title><content type='html'>&lt;p&gt;One of the best new features of the upcoming REBOL 3 is the module system. I&amp;rsquo;m not going to go into the rationale behind modules, but I would like to make a proposal about module names.&lt;/p&gt;

&lt;p&gt;Every module can optionally have a name. A name is required if the module author wishes to export words from the module. If the module is contained in a file, it&amp;rsquo;s important to note that the module name and the file name need not be the same. REBOL uses the module name to ensure that a module is never loaded twice. This allows us to &lt;span class=&quot;pre&quot;&gt;import&lt;/span&gt; the module as often as we like without incurring any additional overhead.&lt;/p&gt;

&lt;p&gt;The name of a module must be a valid REBOL word. Many REBOL programmers are used to REBOL&amp;rsquo;s &quot;programming in the small&quot; (PITS) philosophy, so I think their tendency will be to use simple module names. However, modules are not a PITS feature, they are a &quot;programming in the large&quot; (PITL) feature. Using simple module names will decrease the opportunity for reuse by making collisions more likely.&lt;/p&gt;

&lt;p&gt;So my proposal is to take a page from Java and use package-style module names. Fortunately, the &quot;.&quot; character is perfectly valid inside a REBOL word and has no particular meaning as it does in other languages. Here are some examples:&lt;/p&gt;

&lt;table class=&quot;pre&quot;&gt;
&lt;tr&gt;
&lt;td&gt;com.rebol.math&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net.revolucent.math&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;As you can see, these are names for math modules. My fear is that many REBOL programmers will release modules naively named &quot;math&quot; and this will make it much harder to use them together. By hijacking Java&#39;s simple convention of reverse domain names, the problem is neatly solved.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.revolucent.net/feeds/5262029759364635407/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.revolucent.net/2009/10/rebol-module-names.html#comment-form' title='30 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/5262029759364635407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/5262029759364635407'/><link rel='alternate' type='text/html' href='http://blog.revolucent.net/2009/10/rebol-module-names.html' title='REBOL Module Names'/><author><name>Gregory Higley</name><uri>http://www.blogger.com/profile/01615990128586180796</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>30</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5564756944652168330.post-2495506657174489514</id><published>2009-07-05T06:32:00.006-04:00</published><updated>2009-07-07T07:24:33.531-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Bindology"/><category scheme="http://www.blogger.com/atom/ns#" term="dsl"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="REBOL"/><title type='text'>Deep REBOL: Bindology</title><content type='html'>&lt;p&gt;
 I&amp;rsquo;m often asked why I think REBOL is a &amp;ldquo;deep&amp;rdquo; language. This question is no surprise. REBOL&amp;rsquo;s ordinary syntax &amp;mdash; the so called &lt;span class=&quot;pre&quot;&gt;DO&lt;/span&gt; dialect &amp;mdash; is unlikely to be very impressive to a veteran Ruby, Haskell, or C# programmer. E.g.,
&lt;/p&gt;
&lt;pre&gt;foreach x [1 2 3] [
    print x
]&lt;/pre&gt;
&lt;p&gt;
 While I think the simplicity of the &lt;span class=&quot;pre&quot;&gt;DO&lt;/span&gt; dialect is a strength, it causes many &amp;mdash; probably most &amp;mdash; developers to dismiss REBOL out of hand. But those that stick around eventually discover that there&amp;rsquo;s more to REBOL than meets the eye.
&lt;/p&gt;
&lt;p&gt;
 REBOL&amp;rsquo;s depth comes from the runtime behavior of three special datatypes, &lt;span class=&quot;pre&quot;&gt;word!&lt;/span&gt;, &lt;span class=&quot;pre&quot;&gt;block!&lt;/span&gt; and &lt;span class=&quot;pre&quot;&gt;object!&lt;/span&gt;, optionally combined with the power of the &lt;span class=&quot;pre&quot;&gt;PARSE&lt;/span&gt; dialect.
&lt;/p&gt;
&lt;p&gt;
 REBOL words are the symbols of the language, such as &lt;span class=&quot;pre&quot;&gt;foreach&lt;/span&gt;, &lt;span class=&quot;pre&quot;&gt;x&lt;/span&gt; and &lt;span class=&quot;pre&quot;&gt;print&lt;/span&gt; in the example above. The closest equivalent in a traditional programming language is an identifier (or a keyword), except that unlike an identifier, REBOL words are directly and immediately accessible at runtime. There is no special API, such as reflection or runtime type information, required. I urge you not to get too cozy with this idea, however. Though there are some superficial resemblances, REBOL words are neither identifiers nor keywords.
&lt;/p&gt;
&lt;p&gt;
 The most common use of a REBOL word is to serve as a variable. For instance, in the example above the word &lt;span class=&quot;pre&quot;&gt;foreach&lt;/span&gt; serves as a variable pointing to a built-in function that iterates over a series. However, there is no requirement that words serve as variables. They can be used directly as symbols in their own right.
&lt;/p&gt;
&lt;p&gt;
 Blocks are a bit simpler to understand than words, and nearly as ubiquitous. A block is a sequence of zero or more REBOL values (words, integers, strings, urls and so on) enclosed between square brackets. Blocks are not like the curly braces of a language like C. They are actual values and can be (and usually are) passed as arguments to functions. For instance, the &lt;span class=&quot;pre&quot;&gt;foreach&lt;/span&gt; function in the example above takes three arguments. First, a word to serve as the iteration variable. Second, a series of some kind. In this case, the block &lt;span class=&quot;pre&quot;&gt;[1 2 3]&lt;/span&gt;. And lastly, another block containing the code to be executed for each iteration. To make this more explicit, take a look at the following example.
&lt;/p&gt;
&lt;pre&gt;action: [ print x ]
foreach x [1 2 3] action&lt;/pre&gt;
&lt;p&gt;
 (A word with a colon after it is called a &lt;span class=&quot;pre&quot;&gt;set-word!&lt;/span&gt;. The colon is not an operator. It is a part of the word itself and cannot be separated from it. A set-word is used to assign a value to a word. In this case, we are assigning the block &lt;span class=&quot;pre&quot;&gt;[ print x ]&lt;/span&gt; to the word &lt;span class=&quot;pre&quot;&gt;action&lt;/span&gt;.)
&lt;/p&gt;
&lt;p&gt;
 This is functionally equivalent to the first example. It also conveniently points out another interesting fact about REBOL blocks: By default, their evaluation is deferred. The &lt;span class=&quot;pre&quot;&gt;action&lt;/span&gt; block in the example above contains two (literal, unevaluated) REBOL words, &lt;span class=&quot;pre&quot;&gt;print&lt;/span&gt; and &lt;span class=&quot;pre&quot;&gt;x&lt;/span&gt;. It is only when we pass this block as an argument to &lt;span class=&quot;pre&quot;&gt;foreach&lt;/span&gt; that the block is evaluated and the &lt;span class=&quot;pre&quot;&gt;print&lt;/span&gt; word resolves to a function. Note that the act of passing a block as an argument does not necessarily mean it will be evaluated. It depends on the function to which it is passed.
&lt;/p&gt;
&lt;p&gt;
 In order to serve as variables, REBOL words must be bound to a &lt;em&gt;context&lt;/em&gt;, which is a value of type &lt;span class=&quot;pre&quot;&gt;object!&lt;/span&gt;. By default, REBOL provides a global context. Any word not bound to a specific context automatically expands the global context. In fact, the global context is the only context that can be expanded. All other contexts must explicitly declare the words that are bound to them, and once a context is declared, it cannot be expanded further. This is best shown with an example.
&lt;/p&gt;
&lt;pre&gt;x: 99
foo: context [
    x: 17
    print x
]
print x&lt;/pre&gt;
&lt;p&gt;
 Look carefully at the example above. We have two different &lt;span class=&quot;pre&quot;&gt;x&lt;/span&gt;&amp;rsquo;s. The first one is declared and assigned in the global context, and the second is declared and assigned in the &lt;span class=&quot;pre&quot;&gt;foo&lt;/span&gt; context. The second &lt;span class=&quot;pre&quot;&gt;print x&lt;/span&gt; statement prints 99, not 17. These two words are said to have the same spelling, but they &lt;em&gt;are not the same word&lt;/em&gt;. This is an important distinction.
&lt;/p&gt;
&lt;p&gt;
 At first glance, this looks like the ordinary scope rules one finds in a traditional programming language. It&amp;rsquo;s actually more interesting than that. Take a look at another example.
&lt;/p&gt;
&lt;pre&gt;x: 99
xs: []
foo: context [
    x: 17
    append xs &#39;x
]
probe xs
; == [x]
print xs
; == 17&lt;/pre&gt;
&lt;p&gt;
 This example will take some explaining. First, the lines beginning with semicolons are comments. I&amp;rsquo;ve used them here to show what the result of executing the preceding line of code is. So, first we assign the value 99 to the word &lt;span class=&quot;pre&quot;&gt;x&lt;/span&gt; in the global context. We then declare an empty block and assign it to &lt;span class=&quot;pre&quot;&gt;xs&lt;/span&gt;. Then we declare a context and, inside it, we declare another &lt;span class=&quot;pre&quot;&gt;x&lt;/span&gt; bound to that context. We then append the word &lt;span class=&quot;pre&quot;&gt;x&lt;/span&gt; to our block, &lt;span class=&quot;pre&quot;&gt;xs&lt;/span&gt;. The apostrophe is used to say that we want to refer to the word itself, not its value. This means that after &lt;span class=&quot;pre&quot;&gt;append xs &#39;x&lt;/span&gt; is executed, the variable &lt;span class=&quot;pre&quot;&gt;xs&lt;/span&gt; contains &lt;span class=&quot;pre&quot;&gt;[x]&lt;/span&gt;, &lt;em&gt;not&lt;/em&gt; &lt;span class=&quot;pre&quot;&gt;[17]&lt;/span&gt;, as shown by executing the &lt;span class=&quot;pre&quot;&gt;probe&lt;/span&gt; function, which prints out an unevaluated value. The &lt;span class=&quot;pre&quot;&gt;print&lt;/span&gt; function, however, &lt;em&gt;does&lt;/em&gt; evaluate its argument. In this case, it prints 17. (When passed a block, &lt;span class=&quot;pre&quot;&gt;print&lt;/span&gt; spits out all the values with a single space between them. If there&amp;rsquo;s only one value in the block, it&amp;rsquo;s just printed as-is.)
&lt;/p&gt;
&lt;p&gt;
 Why didn&amp;rsquo;t &lt;span class=&quot;pre&quot;&gt;print xs&lt;/span&gt; spit out 99? How did &lt;span class=&quot;pre&quot;&gt;print&lt;/span&gt; know which &lt;span class=&quot;pre&quot;&gt;x&lt;/span&gt; to print? &lt;em&gt;REBOL words carry a reference to their context with them.&lt;/em&gt; It&amp;rsquo;s not where a word is evaluated that makes the difference, but where it&amp;rsquo;s declared. Because of this, it&amp;rsquo;s entirely possible to have a block containing &lt;span class=&quot;pre&quot;&gt;[x x x]&lt;/span&gt; in which each &lt;span class=&quot;pre&quot;&gt;x&lt;/span&gt; was declared in a different context and each one has a completely different value! In fact, I think it would be useful to show just such an example.
&lt;/p&gt;
&lt;pre&gt;xs: []
use [x] [
    x: 12
    append xs &#39;x
]
use [x] [
    x: 9
    append xs &#39;x
]
use [x] [
    x: &quot;REBOL&quot;
    append xs &#39;x
]
probe xs
; == [x x x]
print xs
; == 12 9 REBOL&lt;/pre&gt;
&lt;p&gt;
 The &lt;span class=&quot;pre&quot;&gt;use&lt;/span&gt; function creates an anonymous context. The first block passed to it contains declarations of the words that are bound to the anonymous context, and the second block contains any code we wish to execute in that context. The important thing to note here is that the &lt;span class=&quot;pre&quot;&gt;xs&lt;/span&gt; variable ends up containing &lt;span class=&quot;pre&quot;&gt;[x x x]&lt;/span&gt;. Although each of these words has the same spelling, &amp;ldquo;x&amp;rdquo;, they are not the same word. Each is declared in a different context and points to a different value. This is demonstrated by printing the values.
&lt;/p&gt;
&lt;p&gt;
 The relationship between words and contexts is known as &lt;em&gt;Bindology&lt;/em&gt; in REBOL jargon. Fortunately, it isn&amp;rsquo;t necessary to have a deep understanding of Bindology to write basic REBOL code, but (in my humble opinion) it&amp;rsquo;s indispensible for doing anything advanced.
&lt;/p&gt;
&lt;p&gt;
 Once I&amp;rsquo;d figured all of this out, I thought it was extremely interesting, and a very unique way to design a language. But my first thought after that was to ask myself why anyone would design a language this way. What does it gain you? While you can do some very useful things with it, I think the answer lies in the ability to create REBOL dialects.
&lt;/p&gt;
&lt;p&gt;
 In REBOL, a &lt;em&gt;dialect&lt;/em&gt; is a sequence of REBOL values inside of a block, interpreted using the &lt;span class=&quot;pre&quot;&gt;parse&lt;/span&gt; function. This is more easily demonstrated than explained, so here&amp;rsquo;s an example.
&lt;/p&gt;
&lt;pre&gt;rules: [
    any [
        set count integer!
        set value [ string! | word! ] (value: either string? value [value] [get value])
        (repeat n count [print value])
    ]
]
last-name: &quot;Sassenrath&quot;
parse [3 &quot;Carl&quot; 4 last-name] rules
&lt;/pre&gt;
&lt;p&gt;
  The second argument of &lt;span class=&quot;pre&quot;&gt;parse&lt;/span&gt; is a block specified in the &lt;span class=&quot;pre&quot;&gt;PARSE&lt;/span&gt; dialect, the syntax of which is (far) outside the scope of this blog post. Suffice it to say that these rules provide the grammar for a very simple dialect. This dialect must consist of a sequence of zero or more integer-string or integer-word pairs. For each pair encountered, the string is printed out the number of times specified. If a word is encountered, it is evaluated, and the result is also printed to standard output.
&lt;/p&gt;
&lt;p&gt;
 This isn&amp;rsquo;t a very useful or complex dialect, but truly, the sky&amp;rsquo;s the limit. The only proviso is that the dialect must consist of a sequence of valid REBOL values, optionally including words. Note that dialects could not exist if blocks were immediately evaluated. By deferring their evaluation, we give &lt;span class=&quot;pre&quot;&gt;parse&lt;/span&gt; the opportunity to interpret the block in whatever way we wish, completely bypassing REBOL&amp;rsquo;s ordinary &lt;span class=&quot;pre&quot;&gt;DO&lt;/span&gt; dialect. We also have the opportunity, using Bindology, to evaluate any REBOL words that are included in the dialect, if we wish to do so and if our grammar permits them.
&lt;/p&gt;
&lt;p&gt;
 In sum, Bindology allows us to defer the execution of blocks for various purposes, including the specification of dialects, while allowing us to include REBOL words in the block without fear of side effects. This allows for some very powerful and unique methodologies, and it&amp;rsquo;s what gives REBOL its depth.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.revolucent.net/feeds/2495506657174489514/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.revolucent.net/2009/07/deep-rebol-bindology.html#comment-form' title='323 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/2495506657174489514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/2495506657174489514'/><link rel='alternate' type='text/html' href='http://blog.revolucent.net/2009/07/deep-rebol-bindology.html' title='Deep REBOL: Bindology'/><author><name>Gregory Higley</name><uri>http://www.blogger.com/profile/01615990128586180796</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>323</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5564756944652168330.post-7735041040335534735</id><published>2009-05-24T08:12:00.009-04:00</published><updated>2009-05-24T09:18:03.743-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="REBOL"/><title type='text'>JavaScript &amp; REBOL</title><content type='html'>&lt;p&gt;After working with both languages a great deal, I&amp;rsquo;ve come to the realization that JavaScript is the language in common use that&amp;rsquo;s most akin to REBOL. There&amp;rsquo;s still a very wide gulf, but there are enough similarities to make it worth a mention. (Not much more than a mention, though.)&lt;/p&gt;

&lt;p&gt;At first glance, JavaScript and REBOL don&amp;rsquo;t look much alike, even when the code is doing the same thing.&lt;/p&gt;

&lt;pre&gt;// JavaScript
function foo(s) {
 return s + &#39;foo&#39;;
}&lt;/pre&gt;

&lt;pre&gt;; REBOL
foo: func [s [string!]] [
 rejoin [s &quot;foo&quot;]
]&lt;/pre&gt;

&lt;p&gt;We can start to make them look a little more similar if we put the JavaScript inside an object literal and the REBOL inside a block. We&amp;rsquo;ll also
omit the type specifier from the REBOL function, since JavaScript has no equivalent.&lt;/p&gt;

&lt;pre&gt;{
 foo: function(s) {
  return s + &#39;foo&#39;;
 }
}&lt;/pre&gt;

&lt;pre&gt;[
 foo: func [s] [
  rejoin [s &quot;foo&quot;]
 ]
]&lt;/pre&gt;

&lt;p&gt;(I should point out that a block and an object literal are not equivalent, but their capabilities overlap a little bit. REBOL&amp;rsquo;s blocks are much more powerful.)&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s about as far as we can go with that. Anyway, it&amp;rsquo;s not &lt;em&gt;lexical&lt;/em&gt; similarity that concerns me here, but &lt;em&gt;functional&lt;/em&gt; similarity. For instance, both languages are scripting languages in the sense that they are not (usually) compiled. No big deal there. That&amp;rsquo;s true of a long list of languages.&lt;/p&gt;

&lt;p&gt;However, both languages are prototype languages, and that&amp;rsquo;s certainly not true of a lot of languages.&lt;/p&gt;

&lt;pre&gt;function Foo() {
 this.watusi = 3;
}

function Bar() {
 this.watusi = 4;
}

Bar.prototype = Foo;&lt;/pre&gt;

&lt;p&gt;In REBOL, it&amp;rsquo;s similar, although in my opinion slightly more elegant, even if its syntax looks a bit strange to the curly bracers.&lt;/p&gt;

&lt;pre&gt;foo: make object! [watusi: 3]
bar: make foo [watusi: 4]&lt;/pre&gt;

&lt;p&gt;The serialized form of both languages is the language itself. In JavaScript, the JSON format is often used as a way to communicate between client and server. A very similar thing can be done with REBOL, although it has no specific name. (There really isn&amp;rsquo;t any need to have a special name or notation in REBOL. It&amp;rsquo;s just REBOL. In fact, being used for messaging is one of the fundamental things REBOL was designed to do.)&lt;/p&gt;

&lt;pre&gt;{ // JavaScript object literal
 orderno: 37,
 items: [22, 873, 14] // A list of order item numbers
}
&lt;/pre&gt;

&lt;p&gt;What you see above is exactly what the server would transmit. We&amp;rsquo;d use it in JavaScript by assigning it to a variable.&lt;/p&gt;

&lt;pre&gt;var order = getOrder(); // getOrder() returns the object literal specified above
alert(order.orderno);&lt;/pre&gt;

&lt;p&gt;Here&amp;rsquo;s one REBOL equivalent (of a great many). Here&amp;rsquo;s what we&amp;rsquo;d transmit:&lt;/p&gt;

&lt;pre&gt;orderno: 37
items: [22 873 14]
&lt;/pre&gt;

&lt;p&gt;And here&amp;rsquo;s how we might use it:&lt;/p&gt;

&lt;pre&gt;order: get-order
print order/orderno&lt;/pre&gt;

&lt;p&gt;The reason I didn&amp;rsquo;t place the REBOL &amp;ldquo;object literal&amp;rdquo; inside a block is because it isn&amp;rsquo;t necessary. When the string is read from the server, the &lt;span class=&quot;pre&quot;&gt;LOAD&lt;/span&gt; function will automatically place it inside a block. &lt;span class=&quot;pre&quot;&gt;GET-ORDER&lt;/span&gt; would be implemented something like this:&lt;/p&gt;

&lt;pre&gt;get-order: does [
 make object! load http://localhost:999/foo
]&lt;/pre&gt;

&lt;p&gt;In this particular case I tried to make the REBOL look as close to the JavaScript as I could to emphasize their similarities. I would probably implement the above very differently in REBOL under ordinary circumstances, although there&amp;rsquo;s nothing wrong with how it was done here. Because REBOL has DSLs and the evaluation of blocks is deferred (unlike JavaScript&amp;rsquo;s object literals), we have quite a few more options.&lt;/p&gt;

&lt;p&gt;Another similarity is that both languages allow functions to be passed as arguments.&lt;/p&gt;

&lt;pre&gt;function callF(f) {
 f();
}

callF(function(){
 alert(&#39;called!&#39;);
});&lt;/pre&gt;

&lt;pre&gt;call-f: func [f [any-function!]] [
 f
]

call-f does [print &quot;called!&quot;]&lt;/pre&gt;

&lt;p&gt;Both languages are amazingly nimble, although in a flexibility contest REBOL would win easily. It can do everything JavaScript can do and then some.
Everything except manipulate the DOM, that is.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.revolucent.net/feeds/7735041040335534735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.revolucent.net/2009/05/javascript-rebol.html#comment-form' title='46 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/7735041040335534735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/7735041040335534735'/><link rel='alternate' type='text/html' href='http://blog.revolucent.net/2009/05/javascript-rebol.html' title='JavaScript &amp; REBOL'/><author><name>Gregory Higley</name><uri>http://www.blogger.com/profile/01615990128586180796</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>46</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5564756944652168330.post-6828016663298792507</id><published>2009-04-26T03:49:00.003-04:00</published><updated>2009-04-26T04:21:38.091-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="dsl"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="REBOL"/><title type='text'>A Dirt-Simple DSL In REBOL</title><content type='html'>&lt;p&gt;REBOL allows the creation of domain-specific languages (DSLs) using the &lt;span class=&quot;pre&quot;&gt;parse&lt;/span&gt; function. It takes as its first argument a &lt;span class=&quot;pre&quot;&gt;block!&lt;/span&gt; containing the DSL and as its second argument another &lt;span class=&quot;pre&quot;&gt;block!&lt;/span&gt; containing the DSL&amp;rsquo;s specification, e.g.,&lt;/p&gt;

&lt;pre&gt;parse [x 2 x &quot;hey!&quot;] [ 
	some [
		&#39;x
		set value [ integer! | string! ]
		(print either integer? value [ value * 2 ] [ value ])
	]
]&lt;/pre&gt;

&lt;p&gt;In this simple (and completely useless) DSL, the literal &lt;span class=&quot;pre&quot;&gt;x&lt;/span&gt; is followed either by an integer or a string. This sequence of &lt;span class=&quot;pre&quot;&gt;x&lt;/span&gt; followed by a value can be repeated indefinitely. (That&amp;rsquo;s what &lt;span class=&quot;pre&quot;&gt;some&lt;/span&gt; tells us in the DSL&amp;rsquo;s specification.) If the value is an integer, it&amp;rsquo;s multiplied by two and then printed. If it&amp;rsquo;s a string, it&amp;rsquo;s simply printed as is. This is accomplished by the code inside of the parentheses. In the &lt;span class=&quot;pre&quot;&gt;parse&lt;/span&gt; dialect, anything in parentheses is interpreted as REBOL code written in the &lt;span class=&quot;pre&quot;&gt;do&lt;/span&gt; dialect, i.e., it&amp;rsquo;s what we think of as ordinary REBOL code. This code is executed only if the previous &lt;span class=&quot;pre&quot;&gt;parse&lt;/span&gt; rule succeeds in matching.&lt;/p&gt;

&lt;p&gt;Most REBOL DSLs are declarative, because those are the easiest sort to write, but if you&amp;rsquo;re motived you can create any sort of DSL you wish. It should be stressed that REBOL DSLs are &lt;em&gt;dialects of REBOL&lt;/em&gt;, not completely new languages in their own right. In fact, they are dialects of REBOL&amp;rsquo;s &lt;em&gt;data exchange dialect&lt;/em&gt;, because the only valid lexical items are those that are valid in that dialect. For instance, &lt;span class=&quot;pre&quot;&gt;@&lt;/span&gt; by itself is not a valid REBOL literal, and thus cannot be used directly in any REBOL DSL. Thus, the following is not valid:&lt;/p&gt;

&lt;pre&gt;parse [2 @ 3] grammar&lt;/pre&gt;

&lt;p&gt;However, the following is valid because &lt;span class=&quot;pre&quot;&gt;@&lt;/span&gt; appears as part of an email address, which is a valid REBOL literal.&lt;/p&gt;

&lt;pre&gt;parse [2 test@test.com 3] grammar&lt;/pre&gt;

&lt;p&gt;DSLs can be used for whatever purpose you wish, but most recently I created a DSL to do list comprehensions, since they aren&amp;rsquo;t natively supported in REBOL. E.g.,&lt;/p&gt;

&lt;pre&gt;list [[a * b] for a in [1 2 3] for b in [4 5 6] where [even? a * b]]&lt;/pre&gt;

&lt;p&gt;This returns &lt;span class=&quot;pre&quot;&gt;[4 6 8 10 12 12 18]&lt;/span&gt;. Here&amp;rsquo;s the source. It depends on the &lt;span class=&quot;pre&quot;&gt;range&lt;/span&gt; function which I&amp;rsquo;ve also added.&lt;/p&gt;

&lt;pre&gt;range: func [pair [pair! block!] /local min max result][
    min: first pair 
    max: second pair 
    result: copy [] 
    for n min max either min &amp;#60; max [1] [-1] [
        append result n
    ] 
    result
]
	
list: func [
	{Performs a list comprehension.}
    comprehension [block!] 
    /type 
    	datatype [datatype!] 
    /local 
	    args 
	    action 
	    elems 
	    filter 
	    index 
	    list 
	    result 
	    rules 
	    skip 
	    vars
][
    vars: make object! [] 
    rules: [
        set action [block!] 
        some [
            &#39;for 
            set var word! 
            &#39;in 
            set list [word! | series! | pair!] 
            (if pair? list [list: range list]) 
            (vars: make vars reduce [to-set-word var either paren? list [do list] [list]])
        ] 
        opt [
            &#39;where 
            set filter [block!]
        ]
    ] 
    unless parse comprehension rules [
        make error! &quot;The list comprehension was not valid.&quot;
    ] 
    action: func copy at first vars 2 action 
    filter: func copy at first vars 2 either found? filter [filter] [[true]] 
    elems: 1 
    foreach field at first vars 2 [
        unless found? result [
            result: make either type [datatype] [type? vars/(field)] none
        ] 
        elems: elems * (length? vars/(field))
    ] 
    for n 0 (elems - 1) 1 [
        skip: elems 
        args: copy [] 
        foreach field at first vars 2 [
            list: vars/(field) 
            skip: skip / length? list 
            index: (mod to-integer (n / skip) length? list) + 1 
            append args list/(index)
        ] 
        if do compose [filter (args)] [
            append/only result do compose [action (args)]
        ]
    ] 
    result
]&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.revolucent.net/feeds/6828016663298792507/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.revolucent.net/2009/04/dirt-simple-dsl-in-rebol.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/6828016663298792507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/6828016663298792507'/><link rel='alternate' type='text/html' href='http://blog.revolucent.net/2009/04/dirt-simple-dsl-in-rebol.html' title='A Dirt-Simple DSL In REBOL'/><author><name>Gregory Higley</name><uri>http://www.blogger.com/profile/01615990128586180796</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5564756944652168330.post-6957410437556421150</id><published>2009-04-24T00:08:00.037-04:00</published><updated>2009-05-02T18:12:16.985-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="REBOL"/><title type='text'>REBOL</title><content type='html'>&lt;p&gt;When I first looked at &lt;a href=&quot;http://www.rebol.com&quot;&gt;REBOL&lt;/a&gt;, I didn’t think much of it:&lt;/p&gt;&lt;pre&gt;foreach e [1 2 3] [
   print e
]&lt;/pre&gt;

&lt;p&gt;Pretty obvious what this does, and it’s the sort of thing you’ve seen a million times, eh? Not to mention the square brackets …&lt;/p&gt;

&lt;p&gt;But then I saw stuff like this:&lt;/p&gt;

&lt;pre&gt;write/binary %Google.html read/binary http://www.google.com&lt;/pre&gt;

&lt;p&gt;That started to pique my interest! I can&#39;t think of another language in which writing the contents of a URL to a file are so concise. It might as well be &lt;span class=&quot;pre&quot;&gt;wget&lt;/span&gt; or &lt;span class=&quot;pre&quot;&gt;curl&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;I noticed a few other strange things about this syntax as well. First, the URL was not quoted. It was just written out as is. And the file name was prefixed by a percent sign. I had to know more about this, and what I discovered was much deeper than I ever expected.&lt;/p&gt;&lt;p&gt;Like all programming languages, REBOL has tokens whose type can be determined by their lexical form. To give a common example, when an interpreter or compiler encounters the token &lt;span class=&quot;pre&quot;&gt;3&lt;/span&gt;, it interprets it as an integer (of some kind). These kinds of tokens are usually known as &lt;i&gt;literals&lt;/i&gt;. Most languages have string and numeric literals, and that’s about it. REBOL on the other hand has a &lt;i&gt;lot&lt;/i&gt; of literals: strings, numbers, URLs, blocks, parens, paths, words, files, and so on.&lt;/p&gt;&lt;p&gt;Here are some examples:&lt;/p&gt;

&lt;table border=&quot;0&quot; style=&quot;width: 50%; font-family: Courier; background-color: #eee; margin-top: 1em; margin-bottom: 1em&quot;&gt;&lt;tbody&gt;&lt;tr style=&quot;font-weight: bold; padding-bottom: 0.5em&quot;&gt;&lt;td&gt;Example&lt;/td&gt;&lt;td&gt;REBOL Type&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;integer!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3.2&lt;/td&gt;&lt;td&gt;decimal!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&quot;fish&quot;&lt;/td&gt;&lt;td&gt;string!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;{fish}&lt;/td&gt;&lt;td&gt;string!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;http://www.google.com&lt;/td&gt;&lt;td&gt;url!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ftp://ftp.nowhere.com&lt;/td&gt;&lt;td&gt;url!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;%Google.html&lt;/td&gt;&lt;td&gt;file!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;print&lt;/td&gt;&lt;td&gt;word!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;word:&lt;/td&gt;&lt;td&gt;set-word!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#39;print&lt;/td&gt;&lt;td&gt;lit-word!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;read/binary&lt;/td&gt;&lt;td&gt;path!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;[1 2 3]&lt;/td&gt;&lt;td&gt;block!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;(1 2 3)&lt;/td&gt;&lt;td&gt;paren!&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;There are many more. As you can see, a few of these have equivalents in other languages, but most don’t. In fact, some of these look suspiciously like the kinds of things in which a compiler or interpreter would be interested. That’s true, and it’s the basis of what&#39;s known as the &lt;i&gt;data exchange dialect&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;Let’s digress a bit. REBOL is composed of a hierarchy of dialects. There are several built-in dialects, and REBOL gives developers the ability to create their own. The basis of all the dialects is the data exchange dialect, which isn’t a programming language &lt;i&gt;per se&lt;/i&gt;. It&#39;s just a free-form sequence of literals that can be interpreted however one wishes. For example:&lt;/p&gt;

&lt;pre&gt;[http://www.google.com http://www.yahoo.com] fetch no-one@nowhere.com&lt;/pre&gt;

&lt;p&gt;If we were to replace literals above with their types, we&#39;d get&lt;/p&gt;&lt;pre&gt;block! word! email!&lt;/pre&gt;&lt;p&gt;(Yes, email addresses are another literal data type.) The data exchange dialect can be used much like XML. You can pass around chunks of it and the REBOL interpreter will happily tell you what the types and values of the literals are. It makes for a much better XML than XML, in my opinion. Here&#39;s an example:&lt;/p&gt;

&lt;pre&gt;data: load &quot;[http://www.google.com http://www.yahoo.com] fetch no-one@nowhere.com&quot;
foreach literal data [
 print type?/word literal
]&lt;/pre&gt;

&lt;p&gt;The code above prints out the following:&lt;/p&gt;

&lt;pre&gt;block!
word!
email!&lt;/pre&gt;

&lt;p&gt;When the &lt;span class=&quot;pre&quot;&gt;load&lt;/span&gt; function is passed a string, it interprets the contents of the string as a sequence of literals, and returns a &lt;span class=&quot;pre&quot;&gt;block!&lt;/span&gt; containing those literals. Thus, the &lt;span class=&quot;pre&quot;&gt;data&lt;/span&gt; variable has the following value:&lt;/p&gt;&lt;pre&gt;[[http://www.google.com http://www.yahoo.com] fetch no-one@nowhere.com]&lt;/pre&gt;&lt;p&gt;So, if the block above is an example of the data exchange dialect, what dialect is actual programming code written in? The DO dialect. Ordinarily, when the REBOL interpreter starts processing a file, it assumes that the file is written in the DO dialect. Like all dialects, the DO dialect is a stream of literals whose types are determined by the rules of the data exchange dialect. However, what is done with them afterwards is determined by the rules of the DO dialect.&lt;/p&gt;&lt;p&gt;For example, when the DO dialect encounters the literal* &lt;span class=&quot;pre&quot;&gt;print&lt;/span&gt;, it says, &quot;Ah! This is a literal of type &lt;span class=&quot;pre&quot;&gt;word!&lt;/span&gt;&quot;. It then looks up the value of that word and finds that it points to a function taking a single argument. It then prints the value of that argument to standard output. E.g.,&lt;/p&gt;&lt;pre&gt;print &quot;REBOL&quot;&lt;/pre&gt;&lt;p&gt;This does exactly what one would expect.&lt;/p&gt;&lt;p&gt;All of this barely scratches the surface of REBOL. There&#39;s the syntax of the DO dialect, those strange beasts called &lt;i&gt;words&lt;/i&gt;, &lt;a href=&quot;http://www.fm.tul.cz/~ladislav/rebol/contexts.html&quot;&gt;Bindology&lt;/a&gt; and contexts, and so on. The purpose of this post was to get you interested. Hopefully you&#39;ll read more at &lt;a href=&quot;http://www.rebol.com/&quot;&gt;rebol.com&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;*Note that strictly speaking, &lt;span class=&quot;pre&quot;&gt;print&lt;/span&gt; is a literal in the data exchange dialect, but a token in the DO dialect. However, in the interests of reducing confusion, I stuck with the former term.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.revolucent.net/feeds/6957410437556421150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.revolucent.net/2009/04/rebol.html#comment-form' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/6957410437556421150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/6957410437556421150'/><link rel='alternate' type='text/html' href='http://blog.revolucent.net/2009/04/rebol.html' title='REBOL'/><author><name>Gregory Higley</name><uri>http://www.blogger.com/profile/01615990128586180796</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5564756944652168330.post-7198251943306531562</id><published>2008-06-14T06:33:00.008-04:00</published><updated>2008-06-14T07:01:46.376-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="constraints"/><category scheme="http://www.blogger.com/atom/ns#" term="databases"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="rails"/><category scheme="http://www.blogger.com/atom/ns#" term="ruby"/><title type='text'>Why CHECK Constraints Matter</title><content type='html'>&lt;span class=&quot;Apple-style-span&quot;   style=&quot;  ;font-family:Verdana;font-size:13px;&quot;&gt;&lt;p&gt;Well-written applications validate their data. No one disputes that. The debate has always been: &lt;em&gt;Where should the validation logic go?&lt;/em&gt;&lt;/p&gt;&lt;p&gt;David Heinemeier Hansson, the inventor of Ruby on Rails, strongly believes that validation and other business logic belong in an ORM layer. I don’t think Hansson would fault anyone for putting check constraints in the database. He’d just think you were wasting your time, and violating one of the first principles of Rails development: Don&#39;t Repeat Yourself. In order to take advantage of Rails’ built-in validation machinery, you’ll have to repeat your constraints in the ORM anyway. So why bother putting them in the database at all?&lt;/p&gt;&lt;p&gt;In the case of most Rails applications, I can’t argue with him. The software behind this blog follows exactly that approach and doesn’t suffer. However, this blog is typical of a class of applications in which the database and the application are very tightly bound. They form a single, inseparable unit and the database is not shared.&lt;/p&gt;&lt;p&gt;This arrangement is not typical in the corporate world. There, databases are shared resources accessed by multiple applications, often with a mixture of data access technologies. The mixture arises because databases tend to outlast the technologies that are used to access them. SQL Servers in a Microsoft shop (for instance) may get upgraded, but ODBC, RDO, ADO, and ADO.NET have come (and in some cases gone), not to mention the vast array of DALs and ORMs built atop them.&lt;/p&gt;&lt;p&gt;The database is where the buck stops, and in a shared environment it’s the one constant you can count on. ORMs and DALs will come and go, but if you throw the database out, only then have you truly hit the reset button. This is why &lt;em&gt;at a minimum your validation logic belongs in the database in the form of CHECK constraints.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;You will almost certainly have to repeat yourself in your DAL or ORM. I see no responsible way around this. But to bet the farm on a chunk of middle-tier code that may not be used everywhere at all times is not a good idea.&lt;/p&gt;&lt;p&gt;I’m not naive enough to believe that CHECK constraints are the holy grail of data integrity. Along with great testing, talented development, and strong domain knowledge, they form one of the pillars of robust application development. (And they’ll help you build better ORMs, too!)
&lt;/p&gt;&lt;p&gt;For the record, I’m not an opponent of ORMs. I think they can serve a very useful purpose. Many ORMs have powerful facilities to interact with the user interface and present the opportunity to fix a problem before it gets written to the database. However, no matter how sophisticated the business rules are in the ORM, the database should be the final arbiter of its own data integrity.&lt;/p&gt;&lt;p&gt;Note: This article was originally hosted on my own server in blogging software I&#39;d written myself in RoR.&lt;/p&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.revolucent.net/feeds/7198251943306531562/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.revolucent.net/2008/06/why-check-constraints-matter.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/7198251943306531562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/7198251943306531562'/><link rel='alternate' type='text/html' href='http://blog.revolucent.net/2008/06/why-check-constraints-matter.html' title='Why CHECK Constraints Matter'/><author><name>Gregory Higley</name><uri>http://www.blogger.com/profile/01615990128586180796</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5564756944652168330.post-955798931763454318</id><published>2008-03-25T20:40:00.003-04:00</published><updated>2008-06-14T06:42:13.927-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="blogging"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>DIY</title><content type='html'>&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: verdana;&quot;&gt;I originally fired up Panic’s wonderful &lt;/span&gt;&lt;a href=&quot;http://www.panic.com/coda/&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: verdana;&quot;&gt;Coda&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: verdana;&quot;&gt; and, as an exercise in Ruby on Rails, started developing my own blog from scratch. Rails and Coda are so productive that it’s easy to get the basics completed quickly.&lt;/span&gt;&lt;/div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: verdana;&quot;&gt;
&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: verdana;&quot;&gt;So why am I here at Blogger? Because it’s those last little bits that are a real pain. What’s lacking in the equation is &lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-style: italic;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: verdana;&quot;&gt;time&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: verdana;&quot;&gt;. Creating a good commenting system is what finally propelled me to “outsource” the programming to Google. :)&lt;/span&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.revolucent.net/feeds/955798931763454318/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.revolucent.net/2008/03/diy.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/955798931763454318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5564756944652168330/posts/default/955798931763454318'/><link rel='alternate' type='text/html' href='http://blog.revolucent.net/2008/03/diy.html' title='DIY'/><author><name>Gregory Higley</name><uri>http://www.blogger.com/profile/01615990128586180796</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry></feed>