Hacker News new | ask | show | jobs
by srcreigh 1576 days ago
The point about simple evaluation models, while true for basic Racket, is actually the furthest from the truth in idiomatic Racket.

The idiomatic way to solve a problem in Racket is to develop new syntax (and evaluation orders) which are suited to the problem.

In fact, Racket has pythonic list comprehension syntax too:

    (for/list ([x '(2 4 8)]) (sqr x))
It also has lazy evaluation langs, static typecheck pre-eval step langs, DFA compilers, OOP...

Basically the floodgates are open, even if the river is still a bit barren. Every confusing language feature in existence can be added to Racket. The only saving grace is that anyone, including you, can replace it with less confusing syntax / evaluation orders if they so desire.

I wrote a Macro which adds identifiers to your program based on a SQLite database's column names. [0] If the database isn't found your program does not compile. How is that for confusing alternative evaluation order? If that's your nightmare, my point is made.

[0]: http://tech.perpetua.io/2022/01/generating-sqlite-bindings-w...

8 comments

Developing domain-specific languages/minilanguages is claimed by many to be idiomatic for many Lisps.

And DSL is an especially strength of Racket (especially with the syntax objects, pattern-based syntax transformers, module system and submodules, and `#lang`).

But, just to avoid giving non-Racketeers the wrong impression... I don't recall anyone ever calling a piece of Racket code non-idiomatic merely because it didn't introduce a DSL or syntax extension.

In my (abandoned) Racket book, I intended to get people commercial-grade productive the first day, and introducing syntax extension wouldn't come until calendar weeks/months later. (Related: there'd be an entire chapter at the end, entitled "Don't Use `eval`", starting out like: https://lists.racket-lang.org/users/archive/2014-July/063597... :)

I've spent some time looking at Racket open source projects, and I did not come away with the impression that one must start by creating one's own #lang. There are a lot of custom DSLs out there, but it seems to me that most of them come about, not because using Racket compelled the author to create a DSL, but because creating a DSL compelled the author to use Racket. No other platform I know of (not even MPS) seems to even come close in terms of ease of use and number of batteries included.

I could admittedly be projecting here. Wanting to create a DSL is what brought me back to Racket after a long hiatus. But I don't think so. Exhibit B is that, if you go to Racket's Discord or Slack, you'll see that people are mostly discussing how to solve concrete problems with standard language features. The volume of talk about macros and #langs is much, much smaller.

Another example... this Arc code doesn't finish evaluating until a couple round trips with a web browser are finished. Absolutely cursed

    (defop said req
      (aform [w/link (pr "you said: " (arg _ "foo"))
               (pr "click here")]
        (input "foo") 
        (submit)))
(If you didn't know, Arc is implemented in Racket, and powers this site...)

http://paulgraham.com/arcchallenge.html

One thing to note: The reason why SICP uses Scheme is not that the resulting programs are simpler. But instead, the mental model of what is happening under the hood is simpler, and easy to refine as you go along. This makes it possible to come to the end of the class, ready to create your own Scheme interpreter. I don't think that's possible with any of the alternatives, like Python.

I am sure this result was rare, of course, even when it was the introductory at MIT. And as you point out, Racket has changed a lot also. I think it has been some years that Racket stopped calling itself Scheme, feeling the changes they have made have deviated too far.

In my (abandoned) Racket book (which had a very specific positioning), I was going to introduce some of the non-Scheme iterators like `for/list` at the start, to help people do commercial work on the first day... and then later teach some more old-school Scheme-idiomatic ways to do things, with named-`let` and avoiding mutations to shoehorn. (Then, once people were comfortable with the less-familiar way, they could decide when to use which.)
> I wrote a Macro which adds identifiers to your program based on a SQLite database's column names.

Cool! F# has "type providers" which seem to be similar to this. Do you have any experience with them? I haven't used them but this sounds like an extremely powerful idea that more languages should adopt.

Thanks! I found some type providers docs [0] which is at some level an ML version of my Racket blog post. I had no idea type providers existed. The closest inspiration I had was probably Kotlin SQLDelight or Hibernate java codegen which (probably unnecessarily) requires in-code annotations. Anyway, that's very cool!

The F# type provider looks so stateful ;) Although they are pretty similar, I think the racket pattern syntax is very beautiful. Once you grok the pattern variables vs syntax objects vs quoted lisp data anyways.

Racket actually generates code. It could generate Typed Racket type expressions too. It makes me wonder how LINQ is implemented--my lisp hubris makes me guess it's not as simple as the equivalent Racket macro, but I could be wrong.

I guess Protocol buffers are a mainstream similar system to all this--take CSV file input instead of proto file input. Of course that requires an external compiler for most languages, whereas the racket protocol buffer plugin basically just converts the .proto file to S-expressions and all the codegen happens within Racket ;p

[0]: https://docs.microsoft.com/en-us/dotnet/fsharp/tutorials/typ...

F# has this kind of stuff also, where it will dynamically type data dynamic sources like databases or rest calls, etc. for an example https://fsprojects.github.io/FSharp.Data/
It's not really dynamic typing, because it's happening at compile time. Really type providers are just a specific, restricted form of code generation.
You're a lot more pessimistic here than in your blog post!
Not really. I'm just saying the same stuff in a different #lang-- I mean in different words :p
That is awesome.