4 ms·
This was my experience with Ruby. The language makes it easy to create DSLs, so lots of libraries are implemented that way. To work on a large project you actua
by foreigner 4y ago
This was my experience with Ruby. The language makes it easy to create DSLs, so lots of libraries are implemented that way. To work on a large project you actually need to learn dozens of different languages. No thanks.
- brainbag 4y agoThis used to be the case, but once Ruby stopped being the hot language, the examples of "just because you can doesn't mean you should" went to JS. Rake and RSpec format are the only two DSLs that get any major use anymore, and most other spec tools in other languages use similar describe/it DSLs to RSpec.
- giraffe_lady 4y agoOver the last couple years a way I've come to view software is that a sufficiently complex library, class, api, or even just file IS a DSL. I don't see a useful clear line between "code" and "dsl" in the end, certainly not one based on whether you still use strictly the syntax of the base language. I don't necessarily like learning a bunch of DSLs either, but I'm not sure the ruby situation is that different from what is always the case, just more honest about it. I've been trying to pay attention to the problems I solve and noticing early when they benefit from being explicitly defined as a little language and it's been quite successful in a few cases. It reminds me of something a mentor pointed out early in my career that has remained a valuable insight: a whole lot of real world logic is implemented with state machines, but the only reliable and maintainable ones are where the author knew that from the beginning. Often we're using a known pattern to solve a problem without recognizing and naming it, so missing opportunities to apply hard-won knowledge and tools from elsewhere.
- lispm 4y ago> Over the last couple years a way I've come to view software is that a sufficiently complex library, class, api, or even just file IS a DSL. Yes. A macro gives a certain programming feature a name and a syntax. But with a function we also need to give it a name and we need to define the arguments. In the case of function arguments, we also need to know what the input and output of those function needs to be. For example in Lisp there is a macro WITH-OPEN-FILE, which opens a file, executes code using the input stream and then closes the file. It also ensures that the file is also closed in case of an error. (with-open-file (stream filename) (read stream)) We now may have two other ways to deal with that often needed functionality: write the code or use a function which does the same (here in this example this is possible, but often a macro does something which a function can't). First we write the code. We may pull this from a snippet library. We have to remember what the primitives are and what they do. (let (stream return-value) (unwind-protect (setf return-value (progn (setf stream (open filename)) (read stream))) (close stream) return-value)) Or we write a function. This gets a name CALL-WITH-OPEN-FILE, a list of arguments and in case of the function it needs to now what the input and outputs are: a stream is the input and the result is arbitrary, but will be returned by CALL-WITH-OPEN-FILE. (call-with-open-file filename (lambda (stream) (read stream))) For the macro we need to know: * the name of the macro * the syntax of the macro: with-open-file (<symbol, non-evaluated> <filename, evaluated>) form* * what the generated code is supposed to do For the function we need to know: * the name of the function * the list of arguments and their order * the types and semantics of the arguments: a filename and a function which takes a stream * what the function is supposed to do The effect is basically the same: both ways are essential leading to a DSL, where the language operators and their usage has to be learned.