DomainSpecificTweaks (DSTs) refers to the less extreme and more common form of EmbeddedDomainSpecificLanguages (EDSLs) where, instead of constructing a scoped sublanguage that follows a fresh syntax, one creates smallish 'tweaks' or 'extensions' to the host language to offer more efficient expression of domain-specific concerns. This distinction is useful. When it comes to ExtensibleProgrammingLanguages and mechanisms for implementing them, DSTs require efforts and integration distinct from full EDSLs. For example, DSTs must naturally interact with one another: if you make four DSTs in a given language scope, then each DST must be capable of ready utilization as a subexpression of any of those other three DSTs. In comparison, EDSLs in the general sense need to be aware enough of their resource context to access objects and services and such (to qualify as 'embedded')... but they do not need to be 'aware' (i.e. integrate, even implicitly) the other EDSLs.
To a programmer, DomainSpecificTweaks often seem like extensions consistent with the rest of the language. In the general sense, even libraries of well-named procedures and OperatorOverloading and use of the MetaObjectProtocol can qualify as DomainSpecificTweaks. It is worth noting that RealMacros, while often lauded for their ability to provide EDSLs, are in practice utilized more often for DomainSpecificTweaks. That is, one can cause RealMacros to parse strings or symbol lists and transform these to arbitrary embedded programs... but such 'RealMacros' would not automatically be aware of the arbitrary other RealMacros in the programming scope.
Support for fully EmbeddedDomainSpecificLanguage, especially if it extends to runtime, may be better for scripting purposes and essentially 'embedding' certain scripts (albeit potentially with CompileTime support, typing, and access to other components from the language), as the whole subprogram can more readily be extracted and moved into other contexts (because one can be certain that there is no dependence upon other EDSLs in the scope).
You cannot obtain arbitrary DSTs or EDSLs - it is never "any language you want". With either of these, you are still limited by the semantics of the host language. For example, if a language provides no mechanisms to support AspectOrientedProgramming (e.g. via extension of the post-processor), then your EDSLs and DSTs also won't support it. Due to EmergentBehavior and FeatureInteraction, KeyLanguageFeatures generally need to be supported more 'deeply' than the shallower 'syntax' extensions typically achieved by use of DSTs and EDSLs. This is a truth that seems to largely obviate most 'semantic' benefits one might attempt to achieve by use of EDSLs and DSTs, reducing it largely to (still important) syntactic benefits of more direct and less voluble expression of desired intent - i.e. reducing 'semantic noise' in the code, making it clearer for both those who know the DSTs and EDSLs. That said, there is much benefit in making said intent more directly accessible for refactoring/optimizing independently of the users.
Most of the StumblingBlocksForDomainSpecificLanguages apply to DSTs. It's interesting to note that since DSTs include domain-specific libraries of functions and macros, this can be said also of such libraries.
I hope the above makes some sense of the ThreadMess below, which seems to be fighting a battle regarding the DifferenceThatMakesNoDifference.
There is a big fight about the proper definition of 'DomainSpecificLanguage', wherein (paraphrased here) SamuelFalvo? operates on the assumption that all programming languages are 'programming specific languages', and his opposition (me) operates on the assumption that 'DomainSpecificLanguage' is described in opposition to 'GeneralPurposeProgrammingLanguage' and thus 'programming' doesn't qualify as 'domain specific'... ass/u/me; it was a big fight about nothing. Most of that particular thread should probably just be deleted and left as a summary; if there is no opposition from SamuelFalvo? it can be done in the near future (20080816).
SmugLispWeenie's claim that Lisp provides a way to create domain specific languages inside itself. It mostly provides domain specific Lisp inside itself, and provides ways to mingle other languages in itself like many other languages do. (That is, if you happen to believe that language is distinguishably different that syntax and notation clearly differentiates a language visually.) If it provided a way to make domain specific languages, it'd let me have languages inside lisp. Languages like the (loop) construct, for example. One way to truly obtain domain specific languages is to fork an interpreter or parse a string.
Sure, but you can't really claim that a DSL embedded in a string is a DSL embedded in the language in which the string is embedded. Nor can you say the same for 'forking' an interpreter over a string or file, which is pretty much the same as parsing a string or file, but with concurrency.
Another way is to write such an interpreter in Lisp itself, interpreting the contents of a string, list, or other data structure.
The SmugLispWeenie's claim it takes too long to make a real domain specific language (i.e. one that could parse a string or be forked). This is due to the cost/benefit tradeoff. In most applications, it isn't necessary to provide a lexer, a parser, a unique symbol table/environment management system, type inferencers, preprocessors, et. al. In most cases, you can get by with the definition of a simple syntax, re-using much of the infrastructure already provided by Lisp. As a result, many DSLs in Lisp do kinda sorta look like they're embedded in Lisp.
However, there are thousands of modules out there that provide domain specific languages already - which can exist in side an imperative program, or be forked as process. There are also DSLs for pure functional languages, too, such as Parsec for Haskell, implementing an LL parser.
For example regex interpreters that parse a string inside your imperative program:
// find this pattern in a string called "testing"
pattern = 't.*st.*';
find(pattern, 'testing');
I will admit, however, that it is hard to discern how this differs significantly from this hypothetical Lisp code:
(find (compile-regex "t.*st.*") "testing")
If we want, we can put Lisp inside our imperative program too:
forkLispInterpretter('lispfile.txt');
And we can embed C in Lisp:
(fork-gcc-on "c-file.txt")
If we want, we can skip the forking and just parse the string using a Lisp module.
import
LispParser?;
lispstring = '(lisp(inside))';
parseLisp(lispstring);
And likewise in Lisp too:
(fork-gcc-on-string "#include <stdio.h>\nint main(int argc, char *argv[]) { printf("Hello world!\n"); return 0; }")
And there are plenty of lisp interpreters, regex specific languages and parsers, INI parsers and languages, SQL parsers and interpreters. None of this requires using lisp, in order to make use of a truly domain specific language like Regex, Ini, SQL, etc. But, then again, we all know that the
concept of DSLs proves independent of any programming language in which an interpreter for it is written. After all, even Forth has a BNF parser DSL in less than 16 lines of code.
One does not have write a domain specific language (roll his own) each time if it is made easy to fork another generous interpreter that someone else has written, or use a generous module that allows one to work on strings inside another language. Even easier would be a consistent Lisp module that already implements the domain specific language via macros and functions on Lisp's lists. That eliminates the need to munge with strings all-together.
I'm fairly certain forking an interpreter has very different properties than use of an embedded DSL. Among other things, you cannot pass parameters in the same manner, and the namespaces become vastly different (i.e. one cannot readily access objects in the program's environment). The concurrency issue is also relevant.
- Non sequitur.
- What makes you think so? Most of the times I want a DSL embedded in a language, it isn't because I want it to have no access at all to the original language's environment. In these cases, calling an interpreter or pounding on strings doesn't do a thing for me - I need an embedded DSL. So "one does not have to write a domain specific language [... paraphrasing ...] if it is made easy to fork an interpreter or work on strings" is simply not true. I don't believe this non sequitur.
- {I agree; it isn't non sequitur. To qualify as embedded DSLs should at least require that they get access to the services and context available in the namespace within which they are embedded on par with other language expressions (which includes being on-par with concurrency semantics).}
Having a truly
domain specific language like SQL, Ini, etc can be much more useful than trying to use (something (that (isn't a language) but just more lisp)). Writing more lisp inside lisp is
just lisp - just as writing a DSL in C is just writing more C, and writing Pascal compilers in machine language is just writing more machine language. It is not a domain specific
language, but
domain specific lisp.
[By analogy, everything you use in computer science is just a domain-specific assembly language.] --AnonymousDonor
Unless there is an exact 1:1 correspondence between source and the exact assembly, independent of context, there is never a leg to stand on in claiming that languages are just syntactic sugar for assembler.
False on all accounts. The whole reason languages other than assembly language exists at all is to avoid the duldrum of having to code in assembly language at all. Hence, all computer languages, ultimately, are domain specific languages for assembly language. C is a DSL for writing operating systems. Pascal is a DSL for writing applications. Lisp is a DSL for lambda expression evaluation. Forth is a DSL for deep-embedded applications. Etc. --SamuelFalvo?
- First, there's a huge vocabulary gap: there is nothing assembler-specific about most domain-specific languages
- Nor is there much of anything C/Oberon/Haskell/Lisp/insert favorite language here specific in most DSLs. The whole purpose of a DSL is, well, to be domain specific.
- Correct. And assembly is not, generally, the chosen domain. C/Oberon/Haskell/Lisp aren't even DSLs.
- Can we both agree that we are not talking about assembly language here, and about programming large-scale applications instead? -sf
- these DSLs aren't describing what the assembler should do or talking about assembly.
- Nobody said they would. Again, the whole purpose of C, Pascal, etc. is to avoid having to do so at all. Consider Fortran -- here is a language that was designed expressly for scientists, for use in scientific computing. COBOL, for use in business, by businessmen. Etc. These are considered "general purpose" languages by today's standards. But, back then, they each had very specific audiences.
- You said, and I quote, "All computer languages, ultimately, are domain specific languages for assembly language." That sounds to me like you're saying that assembly is the domain. It probably isn't what you meant to say, but it is what you said. And I'll note that intended application to a particular field does NOT make a DSL. A language that has features that make it useful for network programming does NOT automatically become a network-support DSL, and Fortran is NOT a scientific DSL. DSL requires supporting a field explicitly.
- Poor wording on my part; I meant to write that HLLs are DSLs on top of assembly, not for assembly. However, the remainder of my argument should have offered enough redundancy to allow the reader to see the gaff. Assembly clearly is not the domain. The domain is the application. It always is your application. To make writing your application easier, you invent a higher level language to do so. 'That language is necessarily a domain-specific language. The domain, IN THIS CASE, is software development itself!
- Well, I'd still need to disagree. Most DSLs I've ever used or written compile down to data in languages that are certainly not assembly. Two examples are lists of business rules, compiling sentences into inference-rules and propositions for an AI, and graph-description languages that take a short description of a graph and compile it into my choice of an adjacency list, matrix, or pair of sets.
- And, generally, when people speak of DSLs, the domain is not the development of the application. E.g. I've seen them used for describing simulations, but never to write the simulator. But we cover definition issues below.
- They describe what parts of the program should do, but how it gets done (at any point below the primitives) isn't relevant.
- Just like a domain specific language.
- Actually, DSLs often skip the "do" part as well. Most DSLs I've ever written just describe something, and let someone else figure out what to do with it. Anyhow, what matters here is the fact that the "how it gets done isn't relevant" relates to the fact that neither DSLs and GeneralPurposeProgrammingLanguages are simply wrappers for one another or assembly.
- I stated twice now that DSLs are not wrappers, and I'm going to say it again: IT DEFEATS THE PURPOSE OF WRITING A DSL TO MIMICK THE LOWER-LEVEL LANGUAGE IN WHICH IT IS WRITTEN IN. If a classic characteristic of a DSL is that the "do" part is elided, and if we agree that C is not a DSL, then tell me where in C I can control register allocation using only pure C? Compiler-specific pragmas and whatnot do not count. I'm talking pure C. Tell me how I can explicitly control branch delay slots on RISC processors using C? Tell me how I can explicitly control the order in which bit fields are assigned using nothing but bit-field notation? Tell me how I can explicitly control how parameters are passed to a function, using only pure function notation? Tell me how . . . Do you see a pattern here? The semantics of the C language elides the how of procedural software development. The purpose of a high level language is always to automate some aspect its user's job. This is precisely my (corrected due to differences in definition; see below) definition of a domain-specific language. As a programmer, you function in the domain of writing programs.' So why shouldn't we have DSLs for writing programs?! That's precisely what C, Pascal, Smalltalk, Forth, Lisp, and so many others, ARE.
- ProceduralProgramming is also not domain-specific. None of the ThereAreExactlyThreeParadigms are domain-specific. The KeyLanguageFeatures are also not domain-specific. Pattern-matching is not domain-specific. Do you see a pattern here?
- Second, there is no equivalence in semantics, and there is no fixed coupling between source and final machine-code output,
- I already said previously that no such equivalence is necessary, and furthermore, utterly defeats the purpose of writing a DSL in the first place. Why would you write a DSL if it simply mimicked the host language in which you wrote it?
- Okay, I wrote the below response first, but I feel I need to ask: When you initially said "False, on all accounts", what, exactly were you referring to? I'm suddenly under the vague impression that you might have jumped the gun here and not thoroughly read the statement, or you might have simply been a bit too sweeping with the "on all accounts". Or perhaps I misinterpreted you when you put your response directly below my own, and you were actually responding to the guy above me. Is one of these possible?
- There was a small paragraph which listed several points, all of which I considered false.
- The equivalence IS necessary IF you are going to claim that a language is just a high-level representation (or syntactic sugar) for another language, including assembler.
- Never having made the claim you think I did, I cannot comment on the correctness of your assertion. But, I can say this much, it has no place in this conversation.
- so it is impossible for one language to be the same as the other
- Something I never argued.
- AND it is impossible for one language to simply be a high-level representation of the other.
- Again, something I never argued. Utter, total, 100%, US RDA certified and approved non sequitur.
- "False, on all accounts..." - you said it; watch what you're arguing more carefully.
- Quote me. Where did I say it? Be sure to include context.
- Where? Just a tad bit above this little squabble, and below my statement: "Unless there is an exact 1:1 correspondence between source and the exact assembly, independent of context, there is never a leg to stand on in claiming that languages are just syntactic sugar for assembler." - me; "False on all accounts [...]''" - your response.
- Static types, for example, have no representation at all in assembly.
- Static typing is a PRIME example of domain specificity. Typing is an attempt to automate the process of ensuring program A can couple with program B without unexpected consequences. That's the whole point, purpose, raison detre behind it. It came about precisely because coders in lower level languages were tired of the laborious, often error-prone task of hand-verification of code.
- Eh? Static typing isn't domain specific at all. I can name at least three domains it's useful in. Most meta-language properties are similar - none of them are domain specific because using language to talk about domains or program for domains is not domain-specific.
- OK, so it's useful in three domains. Does that mean it's useful in ALL domains? Domain specificity isn't all or nothing (or, rather, in this case, ONE or nothing). Automotive repair is pretty domain-specific, but the skills can be applied to other forms of mechanical repair. But, does that mean an auto mechanic can repair jet engines? Even in the auto industry itself, trying to find a company that knows how to rebuild a rotary engine is pretty tough!
- Automotive mechanics is domain-specific. Some of their skills are not. We could create a domain-specific language for them that would be of little use when dealing with jet-engine description or repair... a language with much focus on 'diesel' and 'gas' and 'serpentine belts' and 'transmission'. Figuring out how to make such a language good for programming would be a question... perhaps in creation of vehicle simulators.
- And being 'general purpose' doesn't require being useful in 'all' domains... just a wide spectrum. E.g. a knife is a general-purpose tool, good for cooking, combat, even shaving if you must; indeed, it can be considered 'general-purpose' even though it won't help you much when it comes to finding a solution to the TravelingSalesmanProblem.
- Third, GeneralPurposeProgrammingLanguages like C, Pascal, Lisp, and Forth are not DomainSpecificLanguages.
- You're begging the question. This is a logical fallacy.
- My point was that all languages, short of raw machine language, is a domain specific language.
- And you are wrong, on at least this account. I think, perhaps, you have failed to grok DomainSpecificLanguage. Languages merely possessing features useful to a domain do not become DomainSpecificLanguages. Languages have to simultaneously not be useful outside their target domain to be considered DomainSpecificLanguages. That's what the "specific" means.
- Now that seems outright arbitrary. But this is the source of the argument right here -- a difference in definition. I do not hold this definition to be true. But, knowing that this is your definition, I then have to concede that I now agree with some of your points.
- Ah. Well then. No hard feelings? I suppose we should clean up after ourselves...
- The question is, what is the domain? If the domain is writing operating systems, C is your best bet.
- Pfffffffffffffffffffffffffffft! Uh huh. Maybe it was in, say, 1992. If we were going to write an OS today, your best bet would be to write a dedicated language for it first, just as C was written in the 70s as an aide for writing Unix. The language-design and OS design communities (which are about the same, LanguagesAreOperatingSystems) learned a lot of lessons from the language and past attempts - enough to know we can do much better.
- And yet, we have yet to create any domain-specific language for writing OSes that can top C in overall utility. I admit that I, personally, prefer Forth (precisely because I can morph the language into whatever is suitable for the task), but I'm the weirdo of the bunch on that one. The overwhelming masses of systems coders, who invariably have as much experience as I do in systems coding if not moreso, choose C.
- Choice is often based more on familiarity than suitability. C managed to do what Unix was trying to do, but the last thing this world needs is another Unix clone. If we're going to aim for NewOsFeatures, don't choose C.
- If it is writing space shuttle flight guidance system, Forth or Haskell (I list Forth here because, believe it or not, the SpaceShuttle's flight guidance software is, in fact, coded in Forth). If you're looking to write a unit test language, you might want something like RSpec. If you're looking to just code up a clone of Pong, maybe BASIC is your thing. The point is, HorsesForCourses.
- A DSL for writing OperatingSystems, for example, would possess built-in capability to speak about various operating system components and influences (hardware, drivers, scheduling, policies, etc.)
- Like PL/I? Look where all that ended up.
- PL/I is certainly not a DSL. Heck, it was designed with the opposite intention.
- I was referring to the "capability to speak about various OS components and influences."
- and, if automated, would allow easy construction or configuration of an OperatingSystem based upon source written in the language.
- Yes, pretty much exactly like how C does it.
- Eh, the 'and' isn't accidental here - this is certainly not how C does it. I've read chunks of Linux and Windows code both and I can say with some confidence that neither handle 'policies' or high-level OperatingSystem concepts in any manner even vaguely resembling 'direct'. There is much bailing-wire, hand-waving, and duct-tape going on; what these systems have is an informally specified, buggy, slow, half-implemented OperatingSystem-style-language built via libraries of procedures.
Consider a DSL for business rules that speaks of business services and contracts, legal business entities and agents, transactions, policies, general rules and exceptions to them. How, SamuelFalvo?, would this be a 'domain specific language for assembly'?
Simple. You wrote, in no uncertain terms, that if you code a domain specific language in Lisp, you are just coding in Lisp. You claim, in no uncertain terms, that the result is not a domain specific language.
No I didn't. Someone else wrote that. I was the guy arguing in italics. I said, in no uncertain terms, that there is never a leg to stand on in claiming one language is just syntactic sugar or a high-level representation for another (in this case assembly) unless there is an exact 1:1 correspondence between source and the exact assembly, independent of context.
I called you on your logical fallacy. The reason is that you can #define any language you damn well please in place of Lisp. Why should coding a DSL in C or Qomp be any different than coding a DSL in Lisp? Hint: it isn't. What you ascribe to Lisp also applies to Qomp, whether you like it or not.
Well, that isn't true even if you were directing your comments at someone else. There are two aspects to defining a DSL, and Lisp handles only one of them - manipulation of semantics (via manipulation of the code post-processor - on a rather small scale, too!). Macros are a very limited means of writing a DSL (though they ARE still DSLs).
If you want an uber-powerful approach, use a combination of a modifiable grammar, Explicit manipulation of post-processor (allowing aspecting and code-transforms that have the whole context), and PartialEvaluation (so the costs of these first two features don't accumulate beyond reason). And maybe add a little CompileTimeResolution and FirstClassTypes if you'd like to grab stuff from outside the code. LispMacros are useful, but they are fundamentally constrained to a view of only their parameters rather than their context. There isn't any reason embedded DSLs can't have every feature someone listed. But it is fairly clear that he hasn't a clue how to get there from where he's standing (I have an advantage of having studied this subject in my spare time for about two years for my own language design.)
- Huh? I don't think you really understand that you can write a lexer and parser for any language you want, IN LISP ITSELF, and have it parse symbols stuffed in a list. I'm not talking about just writing a macro here, and a function there, and oh gee, look, I have a DSL. Yes, the latter is what usually happens because it offers the biggest bang for the buck. Very often, that's all that is needed. What someone is complaining about is full-on parsing and lexing and semantic interpretation, and ..., ALL of which are very possible right IN LISP ITSELF. I cannot drive this point home more clearly than this. If you disagree with any word in this paragraph, then you are fundamentally incapable of agreement on the most basic premise in my counter-argument to someone else. --SamuelFalvo?
- Oh yeah? Try WhitespaceLanguage. And if you get that one, go for an aspect-oriented language that actually affects the rest of Lisp properly. I will note that I am fundamentally incapable of agreeing to believe any truth that I consciously don't believe - this isn't a bad thing. I fully agree that Lisp is capable of embedding DSLs of a wide array of classes. But it is simply not true should the challenge-space be as wide as "any language you want".
And since Qomp, like Pascal before it, is a language intended to automate the process of writing software without the duldrums and slavery of using lower-level program representation,
precisely as any domain specific language, one
must conclude that this extends
all the way down to the machine language level.
Here is the inductive proof:
- Let's start with the base case. You are given a new platform on which to code. Your ultimate goal is to implement the aforementioned business DSL. However, you don't feel your time is best spent coding hand-crafted assembly language. Thus, you port a dialect of Qomp or Pascal to the platform. Hence, Qomp/Pascal is a domain-specific language -- a tool to automate the construction of other software systems without having to worry about the mechanics of its machine language underpinnings.
- Base case fails. Qomp/Pascal aren't domain specific languages. "programming" does not count as a domain - or, if it does, you've got yourself a GeneralPurposeProgrammingLanguage by default (a language "specific" (cough, cough) to the wide field called 'programming'). What matters is the domain for the programming language. Use of EBNF to help write a parser for the business rules language would qualify as a DSL since it isn't useful outside the specific domain of writing parsers for other languages.
- No, your rebuttal fails outright. We're just arguing over words now, because you refuse to grok the greater scope of what a "domain" is.
- I know what 'domain' is, and it's rather broad indeed. One could even talk about universal 'domains', such as the 'programming' domain when we're already talking about 'programming' languages. I'm sure you grok what 'specific' means, but it seems you refuse to offer rather critical modifier any weight.
- Let's assume next that you've implemented a whole suite of software intended to construct your target system. Qomp is installed, your linkers are ready, and your shell environment primed. But, you don't want your customers to hack around in Qomp directly. So, you write a programming language for use by your clientelle. This is a domain-specific language -- a tool that allows your customers to automate some or even all of their business infrastructure, without having to worry about the mechanics of its Qomp language underpinnings.
- Ah, so we now have a 'domain-specific' language that isn't effective for programming much more than the business-infrastructure for which it was designed and is, thus, truly domain-specific. And that language is interpreted, along with any necessary context to apply it, by an interpreter written in a language for which I possess no greater desire to hack around in than do my customers - a language good for programming in a wide-variety of domains. This situation is understood.
Note that the form, motives, and end results are identical for
both levels of abstraction. We can generalize this
infinitely higher levels as well. Thus, inductively, I've proven that your claims are generally applicable to all languages, except only machine language. QED.
The point of lisp is providing a protocol to seamlessly integrate all the DomainSpecificLanguages? a big project needs, thus reducing the impact of VendorLockin? through DomainSpecificLanguages?.
Is that right? That is the point of 'Lisp'? Oh, how naive I was thinking that Lisp was created before VendorLockin? and 3rd party AutomatedCodeGeneration was a large issue. I must be mistaken in thinking there was only one other high-level language around at the time (Fortran). I've always thought that the 'point' of Lisp was to create a practical high-level language for List Processing, Math, and other things based on Alonzo Church's LambdaCalculus. But my misunderstanding is corrected. I thank you for it.
The misunderstanding is possibly due to programmers not being used to long-term-evolving languages in these days, where the typical language is embraced and then forgotten when the next hype is bought.
These edits were lost when I submitted my changes to this page. I am really not liking the "Wiki cannot respond to your request" pages. :(
Fully agreed. I'm trying to write a WikiIde with real-time updates...
I declare that Lisp encourages people to make all sorts of Lisps (rather than promoting clear separate languages like say a true SQL or a true non lisp language). And this is the problem with readability - everyone reinvents their own lisp (not a specific clearly defined and structured language).
Most languages offer ways to tweak themselves. Tweaking themselves to be better selves should only go so far - otherwise your language is just a hodgepodge of NothingIsAnything or AnythingIsNothing?. Whether there are truly separate languages existing in a language or not is a LaynesLaw issue regarding the definition of WhatsaLanguage, I suppose. If a language allows modifications inside itself - that is the language you are working with which provides you DomainSpecificTweaks! It's not really a new language, necessarily (LaynesLaw issue).
This page was therefore positively renamed to DomainSpecificTweaks.
Be warned - that too many tweaks, causes complexity and/or unreadability for other programmers. Using too many tweaks is selfish and goes against sharing code with thousands of people. Consider C++. Consider why Paul Graham's store was rewritten (because, apparently, the industry was just not smart enough.. or maybe the code was really complex and tweaked too heavily for real practical world use).
Matz for example says: "A DSL is just an extension of (Ruby's) syntax (with methods that look like keywords) or API that allows you to solve a problem or represent data more naturally than you could otherwise."
Domain specific extensions, or tweaks, in some people's opinion - is a better way to describe the situation than "language".
AprilZeroEight
CategoryLisp