Hacker News new | ask | show | jobs
by millstone 4439 days ago
When I look at that sample, what strikes me is how much the "custom syntax" still looks like a bunch of S-expressions.

How much flexibility does LISP really give you here? For example, say I wanted my DSL to use Python-style significant whitespace instead of brackets. Does LISP make that easy, or is my DSL restricted to using stuff that looks like S-expressions?

3 comments

Racket is somewhat unique in this respect, but it allows you to create dramatically different languages as DSLs.

Consider this example of the experimental "2d" syntax:

  #lang unstable/2d racket
  (require unstable/2d/cond)
 
  (define (same? a b)
    #2dcond
    ╔═════════════╦═══════════════════════╦═════════════╗
    ║             ║       (pair? a)       ║ (number? a) ║
    ╠═════════════╬═══════════════════════╬═════════════╣
    ║ (pair? b)   ║ (and (same? (car a)   ║     #f      ║
    ║             ║             (car b))  ║             ║
    ║             ║      (same? (cdr a)   ║             ║
    ║             ║             (cdr b))) ║             ║
    ╠═════════════╬═══════════════════════╬═════════════╣
    ║ (number? b) ║          #f           ║   (= a b)   ║
    ╚═════════════╩═══════════════════════╩═════════════╝)
Yes, that big ascii-art graph is actually part of the code, not some sort of comment. The 2d syntax allows you to create ascii art truth tables which contain in them code (in this case, in the traditional paren'd style.)

(See http://docs.racket-lang.org/unstable/2d.html for a better explanation and more examples.)

Alternatively, here is an example of typed racket using sweet expressions:

  #lang sweet-exp typed/racket

  define: fact([n : Integer]) : Integer
    if zero?(n)
       1
       {n * fact{n - 1}}
(https://github.com/takikawa/sweet-racket)*
It might not be easy, depending. Without too much trouble you could write a macro for this:

    (my-macro "
    foo
       bar
    baz beez
       zang
          dang
          bang")
and have the macro parse the string manually into something the eval/apply loop understands. But I think it might get funky pretty quick, and you'll likely lose a lot of power in the process.

The example of Hiccup above doesn't add anything new to Clojure's syntax, the DSL is all legal Clojure data structures. That way it inherits all of the power of the underlying language, like if you want to dynamically generate new HTML - that functionality comes from Clojure. But doing that while modifying the syntax for meaningful whitespace wouldn't be easy.

http://readable.sourceforge.net/

from this:

(define (factorial n)

  (if (<= n 1)

    1

    (* n (factorial (- n 1)))))
to this:

define factorial(n)

  if {n <= 1}

    1

    {n * factorial{n - 1}}
and if you want to use parens, they just work (you can mix and match the two whenever you want without issue). That said, even with such things available, most lisp programmers opt to use parens.