rhombus-prototype icon indicating copy to clipboard operation
rhombus-prototype copied to clipboard

Boring Racket

Open jeapostrophe opened this issue 4 years ago • 9 comments

Yongming Shen wrote, "Design and promote a "boring core subset" that an experienced programmer can pick up easily and be as productive as when using an "ordinary programming language", without writing any macros. Macros are awesome, language-oriented programming is also awesome, if Racket 2 without them can be as appealing (minus third-party library aspects) to programmers as Python/Ruby/Go/..., then Racket 2 plus them will certainly win hearts."

"I think Racket is kind of bloated and fragmented (I'm new to Racket, but this is the impression that I got so far). There are a lot of forms that are doing similar but slightly different things (e.g., the many let forms), and features that are not well integrated (the OO system comes to mind). I think it is amazing that all the features and forms that Racket provides can be reduced to a small set of core forms, but programmers don't write programs in the core forms, and I think it is the responsibility of the language designer to carefully craft a small set of forms and features that a programmer can use directly to solve most of the "ordinary programming problems" productively."

jeapostrophe avatar Aug 03 '19 17:08 jeapostrophe

I think this is related to Python's philosophy -- "There should be one-- and preferably only one --obvious way to do it."

the many let forms

This is one thing I definitely agree with. All -values variants are silly. Ideally, I want to unify let and let-values together (or, get rid of -values entirely, see #78).

(let ([x 1]
      [(y z) (values 2 3)])
  (+ x y z))

However, an unfortunate consequence is that

(define (x y) (f))

is ambiguous: is it creating a function of one argument, or define two values?

One way to resolve this ambiguity is to have a special form for defining a function explicitly:

(fun f (x y) (+ x y))

Comparing to the benefit of getting rid of all -values variants, I personally think it's worth it.

Also, is there any case where we want `let` rather than `let*`? In a working code, all `let` can be converted to `let*`, so we might as well default to `let*`.

That was wrong!

Though, I think the let forms will be used very less often once we have define* (see #46).

sorawee avatar Aug 03 '19 20:08 sorawee

Boring Racket could be a great outlet for all the proposals that want to remove language features from Racket2. Some people appreciate having a diversity of forms because they communicate different intention and come with different costs and fit different use cases, and the runtime supports them. Others find that granularity unhelpful and are willing to pay the fixed cost every time they call the function for the reduced vocabulary. It seems unlikely that these two groups will ever be able to coexist within the same space, so why not give them both their own spaces? Hrm, why does this suddenly sound like R7RS large and small ....

tgbugs avatar Aug 04 '19 23:08 tgbugs

Also, is there any case where we want let rather than let*? In a working code, all let can be converted to let*, so we might as well default to let*.

there are cases where I want let and not let*, usually I am using a binding multiple times to compute related values, one of which will shadow the original. A minimal example from the docs:

(let ([x 5])
  (let ([x 2]
        [y x])
     (list y x)))
--> '(5 2)

(let ([x 5])
  (let* ([x 2]
         [y x])
     (list y x)))
--> '(2 2)

howell avatar Aug 05 '19 17:08 howell

I'm new to Racket as well and I'd like to emphasize the feeling of fragmentation I see in the Racket ecosystem, especially coming from Go. And I the solution to this would be much easier than syntax forms.

As a quick example of this, I wanted to do something dealing with an HTTP client and server. This is sort of the thought process I had as a beginner when going through the various packages:

  • net/http-client (this turned out to be too low level)
  • net/url (this did contain the request API I was looking for with get-pure-port)
  • web-server/servlet (sevre/servlet seemed to meet my requirements for a server)
  • web-server/web-server (Maybe this will be helpful)
  • http (It looks like I should use this if I want HTTP1.1)
  • http11 (I'm not sure what the difference between http is. Is this still even being maintained?)
  • simple-http (Could this be what I want? I do want a simple HTTP API)

However, with Go for example, I can import net/http and start being productive right away. The Racket ecosystem requires more time to get familiar with the landscape.

I guess a solution for this would be to reconsider the boundaries for the various packages and have a solid, canonical foundation from which others can build further functionality.

zkry avatar Sep 01 '19 09:09 zkry

There's a fundamental tension between being a research platform and being a production language. Research generally feeds on divergence, production on convergence. Haskell has the same problem with divergence; my impression as an outsider is that they "solve" it by billing Haskell as a research language with production capabilities bolted on. It remains to be seen how they handle growing "industrial Haskell" segment in the coming years.

To be perfectly honest, a lot of these problems are rooted in trying to do too much with too few resources (number of people, amount of commitment, agreement and brainpower). There are different ways to solve it, none of them ideal. For any language that aspires to increase its production market share, compartmentalizing all the "research" and experimentation aspects into their own corner may be a good first move, as already hinted at in this thread.

lassik avatar Sep 01 '19 09:09 lassik

Even at the risk of putting people off: as a frequent user but still half-outsider to Racket, the project is giving off strong and frequent vibes of turning too ambitious for its own good right now. Please remember the second-system effect: the tendency of small, elegant and successful systems to be succeeded by over-engineered, bloated systems due to inflated expectations and overconfidence. None of us are exempt from it. Remember the folk theory about how every other Windows sucks due to the cycle of overconfidence followed by humility. Microsoft has the resources to fail at every other version and then keep going as if nothing happened; do you? People keep bringing up the Python 2 vs 3 lesson in these discussions, and that's great, but is it being taken to heart? You are in the same situation but with vastly fewer resources of all kinds.

Please take a lot of time to ensure reasonable scope and above all, strong commitment from the interest groups you need to sustain the project. When evaluating your userbase, please remember that most people don't like change; they are invested your language for its utility, not for its own sake, and changes mean they have to do more work to do the same thing they could do previously. This attitude of users is the bane of all creators, but it is inescapable and completely sensible.

lassik avatar Sep 01 '19 10:09 lassik

I agree with @zkry in terms of finding it sometimes hard to navigate the web-server things, but I can't tell how different this is from other languages besides Python/Django - and there the benefit is that you have a whole framework and it's easy to find resources and tutorials. It is not obvious to me that Django is less overwhelming or fragmented once you do something outside of what it does right out of the box (and there is so much magic going on...).

@lassik may have a good point on being overly ambitious, I wouldn't know. Still it might be possible to identify a sub-area of Racket that we make boringer. My vote would go to web things, since that's what I use most, but anything that would make a large subgroup of Racketeers/Rhombites would do, without overdoing it.

MarcKaufmann avatar Oct 18 '19 08:10 MarcKaufmann

For some context — I’m an industrial programmer primarily working in JVM-based languages (Java and Scala), Typescript/Javascript and Python.

I think it’s important to separate out the two topics of "boring" in terms of syntatic/core forms (such the points raised by @sorawee and @jeapostrophe) and "batteries included" such as what @zkry is talking about.

In my experience — both are blockers for adoption, but the second issue is one I’m more familiar with.

It’s important to note that even within Python or Java, very few people use the basic HTTP server provided by the core library — third-party dependencies are used. This is because industry trends change quickly, and even in the same problem-space a design which works well for one problem is unlikely to work well for a different one.

I don’t think that it’s a good approach for any language to bundle these trends in the core library — they inevitably become cruft and can oftentimes proliferate badly through an eco-system making them really, really hard to deprecate (for example Java’s original time library, Scala’s XML, Haskell’s Text, inline expressions etc...).

In general, a newcomer to an eco-system can only get a feel of what to use through the community, through learning materials such as blog-posts, talks, tutorials, etc…

In this regard — like with most other niche languages, Racket doesn’t have enough of a user-base for most people to make this evaluation; so I don't feel that any comparison with languages like Python, Go or Java are appropriate from this angle.

One of the solutions which I’ve seen work quite well is having a secondary "official" organization to "bless" a curated set of third-party libraries. This immediately gives newcomers to the community an "anchoring point". I think this approach would work quite well for Racket.

yilinwei avatar Feb 09 '21 21:02 yilinwei

Something that came up recently while I was reviewing the readers for a bunch of different lisp dialects: make the reader boring. Right now the Racket reader is by far the most sane and regular among a wide variety of modern implementations and dialects. However, the Racket reader implements here strings, which add significant complexity to a reader implementation (as do the multi-char # prefixed forms like #hash, but those are perhaps harder to eliminate). Having a boring subset of the full Racket syntax for which it is easy to implement a portable reader would be useful as (among other things) a safe and portable serialization format.

tgbugs avatar Feb 09 '21 22:02 tgbugs