You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: website/blog/yaml-vs-dsl.md
+145-1Lines changed: 145 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -40,7 +40,7 @@ ast-grep does support pattern. It is a concept to match a strcture that contains
40
40
41
41
> your documentation, where you have to extensively explain how pattern syntax works, how pattern syntax works, how metavariables work
42
42
43
-
As stated before, pattern makes ast-grep users' life easier. Explaining how pattern works is necessary to help users understand how to write rules. This is not a sign of a DSL being necessary, but rather a sign of the limitation of pattern: it is not general enough to cover all cases, and you have to communicate to your users how pattern works in your system. For example, see this [tweet](https://x.com/hd_nvim/status/1941876968363798766) about how to write a pattern to match `functtion` declation in JavaScript.
43
+
As stated before, pattern makes ast-grep users' life easier. Explaining how pattern works is necessary to help users understand how to write rules. This is not a sign of a DSL being necessary, but rather a sign of the limitation of pattern: it is not general enough to cover all cases, and you have to communicate to your users how pattern works in your system. For example, see this [tweet](https://x.com/hd_nvim/status/1941876968363798766) about how to write a pattern to match `function` declation in JavaScript. Another brain teaser, how to tell if `$a = $b` is an `assignment_expression` or `field_initializer`?
44
44
45
45
(an [ad-hominen](https://en.wikipedia.org/wiki/Ad_hominem) note: it is ironic to see this argument from a tool without proper documentation. I cannot suspend my suspect whether the author has used pattern to write non-trivial rules at all.)
46
46
@@ -59,3 +59,147 @@ This is a subjective opinion, instead of an fundamental blocker. The author fail
59
59
We can also see using DSL is not subjectively better than YAML as well.
60
60
61
61
## Subjective Comparison of DSL
62
+
63
+
Let's review the DSL mentioned above.
64
+
65
+
### Mix of several different paradigms
66
+
67
+
Biome's DSL is a mix of several different paradigms: declarative, logic, and imperative. Let's see one example:
68
+
69
+
```JavaScript
70
+
`$method($message)` where {
71
+
$method <:`console.log`,
72
+
if ($message <: r"Hello, .*!") {
73
+
$linter ="hello world"
74
+
} else {
75
+
$linter ="not hello"
76
+
},
77
+
register_diagnostic(
78
+
span = $method,
79
+
message = $linter
80
+
)
81
+
}
82
+
```
83
+
84
+
*`$method('$message')` is a declarative pattern matching syntax.
85
+
*`where` and `<:` are related to [logic programming](https://en.wikipedia.org/wiki/Logic_programming#:~:text=Logic%20programming%20is%20a%20programming,solve%20problems%20in%20the%20domain.) paradigm, say, [Prolog](https://en.wikipedia.org/wiki/Prolog) or SQL.
86
+
*`if` is a typical imperative programming paradigm
87
+
88
+
The mixture of paradigms does not blend well. At least, in the eye of a programming language veteran, it is too messy for a DSL for linting or structural search. We are not designing a next-era programming language.
89
+
90
+
### Easy to miss comma
91
+
92
+
Did you notice there is two trailing commas in `$method <: console.log` and if block?
93
+
94
+
```JavaScript{2,7}
95
+
`$method($message)` where {
96
+
$method <: `console.log`, // [!code focus]
97
+
if ($message <: r"Hello, .*!") {
98
+
$linter = "hello world"
99
+
} else {
100
+
$linter = "not hello"
101
+
}, // [!code focus]
102
+
register_diagnostic(
103
+
span = $method,
104
+
message = $linter
105
+
)
106
+
}
107
+
```
108
+
109
+
Without them you will get a syntax error. This is a common problem for beginners to miss commas, a typical pitfall only in DSL. Alas, I can still remeber the old day when C compiler complained about missing semicolon.
110
+
111
+
### Similar basic patterns have distinct syntax appearance
112
+
113
+
There are several different basic patterns in the DSL. Though they are at the similar level of abstraction, their appearance is totally different.
114
+
115
+
```JavaScript
116
+
`console.log($foo)`// pattern
117
+
augmented_assignment_expression(operator = $op, left = $x, right = $v) // syntax node
118
+
r"Hello, (.*)"($name) // regex
119
+
```
120
+
121
+
These patterns are corresponding to `pattern`, `kind` and `regex` in ast-grep. However, they look totally different. You need more learning to pick up these distinct syntax.
122
+
123
+
### Similar syntax appearance have different meaning
124
+
125
+
One common pitfall to design DSL is that similar syntax have different meaning.
### Confusing Concepts of `condition`, `clause` and `modifier`
170
+
171
+
The DSL also has three similar concepts: `condition`, `clause` and `modifier`.
172
+
Introduced in different places, [here](https://docs.grit.io/language/conditions) and [here](https://docs.grit.io/language/modifiers), without clear definition.
173
+
174
+
### Similar patterns but applied in different places
175
+
176
+
Tell the difference between [and](https://docs.grit.io/language/modifiers#and-clause), [any](https://docs.grit.io/language/modifiers#any-clause), [some](https://docs.grit.io/language/modifiers#some-clause) and [every](https://docs.grit.io/language/modifiers#every-clause).
177
+
Confusing? You should learn the difference between meta var in [list pattern](https://docs.grit.io/language/modifiers#list-patterns) and plain meta var. Also, don't confuse list meta var with [spread meta var](https://docs.grit.io/language/patterns#metavariables)
178
+
179
+
### One more thing, variable scope.
180
+
181
+
If you still have patience, you need one last thing to learn: variable scope.
182
+
183
+
I have no better explanation for it since I don't understand it well, so I will quote the [official documentation](https://docs.grit.io/language/bubble):
184
+
185
+
> Once a metavariable is bound to a value, it retains this value throughout the target code. Therefore, the scope of the metavariable spans the entire target file.
186
+
187
+
To fully understand it, you also need to know `bubble`, `bubble($argument)` and pattern auto wrap.
188
+
189
+
190
+
## Conclusion
191
+
192
+
If you also feel confused, you are not alone. Again, the preference of DSL over YAMl is largely subjective.
193
+
194
+
If you think DSL is better, you are right. [You are absolutely right](https://www.reddit.com/r/ClaudeAI/comments/152b51r/you_are_absolutely_right/). In fact, you are [not even wrong](https://en.wikipedia.org/wiki/Not_even_wrong). Since this is a subjective opinion, not an objective fact.
195
+
196
+
If you are a library or framework author, you can make decision based on your own preference. However, mistakenly thinking your preference is objective will lead to confusion and misunderstanding. It may even reflect inferior tech taste and judgement.
197
+
198
+
Consider these points when you want to have objective comparison:
199
+
200
+
* Documentation?
201
+
* User Education? Howe you teach users to write your DSL?
202
+
* Tooling support like [playground](/playground.html).
203
+
* Editor support beyong syntax highlighting. Say LSP.
204
+
* Integration with API, how you bring type-safe DSL into your general purpose programming language, like [graphql](https://github.com/Quramy/ts-graphql-plugin) and [styled component](https://github.com/styled-components/typescript-styled-plugin).
205
+
* Broader ecosystem support, such as GitHub language detection, AI support, etc.
0 commit comments