Hacker News new | past | comments | ask | show | jobs | submit login
State of Clojure 2016 – Results and Analysis (cognitect.com)
249 points by fnordsensei on Feb 7, 2017 | hide | past | web | favorite | 78 comments

Personal story. I originally used Clojure about 5 years ago, built a few websites with it, along with a few other fun projects. My blog is still in Clojure, but nothing impressive.

About 6 weeks ago, I fired up Emacs and tried out Clojure for a new project, and I have to say, it's definitely different and all of the changes are for the better.

1- Cider. I don't know how I lived without this years ago.

2- Security. Ring comes with CRSF tokens by default.

Friend was kind of a pain to use, and this meant that everyone was rolling their own back then. This isn't an issue anymore. That Bedra talk really gave the community some focus, and I'm glad everyone has been working on it.

3- I'm glad to see that libraries have been stable, improved upon, and not abandoned. While this includes lein, of course, so many things that aren't integral, like hiccup, overtone, etc, have been kept up to date for the new versions.

4- Better integration of libraries.

5- Much much much better build experience. Back then, run lein and have fun figuring out what you have to change in what file to get everything up and running. This is no longer the case, everything just works.

Of course, there are still some issues, but I just wanted to focus on the good stuff here.

I love Clojure and have happily been using it in production for 2+ years.

Maybe I'm just used to the error messages, but I'm surprised "finding libraries" wasn't a higher-rated pain point. In many languages (at least in the web dev world) if you find a library that hasn't had commits in a few years, you can safely assume it's out of date. Not so with Clojure, and while this is due to two Good Things -- the stability of the language and the general avoidance of do-everything libs/frameworks -- it still makes it a bit hard to evaluate whether it's a good idea to rely on a given open source library. And good luck sorting through all the ring-<whatever> middleware to find the right one or right mix for you.

That said, I wouldn't go back to non-Clojure tools (for me that's Rails & JS) for most of my use cases (still awaiting a bit of maturation of the react-native wrappers for doing mobile apps. It's possible the benefits already outweigh the compilation/reload time cost, though).

Do you know re-natal? It is very good with a hot reload better than webpack (using figwheel).

I really want to love Clojure. I've been playing with it recently and I still have some hopes for it. I am comparing it to Elixir for my next language of love. I have a lot of experience with Javascript/Node and secondly Ruby.

I want to embrace a functional paradigm. I want to lean on Clojure because of the versatility of also being able to leverage ClojureScript.

So far I have hit some bumps that are a bit frustrating.

1. I changed too many files at once and the stack trace error I got gave me literally 0 clue on what was wrong. It was such a feeling of doom that it scared me on how to debug Clojure apps. The stack trace was full of Java errors and nothing pointing me in the direction of where the app was failing from Clojure's perspective.

2. Momentum of Web-Development and embracing new technology. I really believe in GraphQL and there isn't much support or conversations with using GraphQL with Clojure and ClojureScript.

3. I want to code Lisp better, but I'm not sure how to learn all the tricks on using Paredit. I use Spacemacs in Vim mode and a lot of the tutorials I see are of course in Emacs bindings so getting the know-how of navigating s-expressions in Spacemacs evil mode is quite the challenge but I'm going for it.

4. Boot up time is lame but it is what it is. `lein run` then `lein cljsbuild auto` can take ~20-30 seconds on a relatively fresh project on my MBA. After the initial boot time it's fine though.

Overall I have my head up high but those are some of the things I'm struggling with. I really want to love Clojure/lisp. I worry most about the community not being large enough to share examples of how to do new things. Which of course can be argued for the better (not a trendy community) but it instills worry nonetheless, especially when one really wants to adopt a tech all around (like GraphQL). I have an argument in my head that shouts "Well, if there's so much momentum in Javascript/Node for that ecosystem then might as well use that. Or even Elixir with Absinthe" – in the end it's about productivity right? :) Anyway rambling at this point.

1. To understand Clojure stacktraces you should read https://8thlight.com/blog/connor-mendenhall/2014/09/12/cloju.... Although I agree the lengthy huge Java dump when crashing is pretty awful, you can ignore most of it.

3. I would recommend you look into Parinfer - https://shaunlebron.github.io/parinfer/. You can manage scopes with levels of indentation, rather than having to move parens around. It works with most major editors, including Emacs.

I couldn't get Parinfer to work with Vim. There's a port but it's buggy.

But the Neovim port is great. Installation requires a little patience, but it works well.

In any case, one should read the Clojure style guide on GitHub [0] and get used to writing code in normal editing modes first. Then move on to Parinfer or Paredit once you feel the shape of the code and sense why it's like that.


Hi - I'm the author of the Parinfer Vimscript port.

If you've found a bug with the port, please report it here: https://github.com/oakmac/parinfer-viml/issues/new

Thanks :)

Is it impossible to implement restarts (a la CL) in Clojure? They are way better than when the interpreter tells me that my program is dead and here's what happened. It's sad that interactive debugging within the repl is not embraced by everybody.

There are some libraries for this. A great overview of the problem and some of the libs is https://www.youtube.com/watch?v=zp0OEDcAro0 and a good set of corresponding notes at https://gist.github.com/msgodf/6f4e43c112b8e89eee3d

I think some of your frustrations might stem from your workflow. You really have to use the REPL to get the most out of Clojure development.

For example, you should never change a bunch of code in different files and then try to run it and hope it works. Clojure workflow would be to change a particular function, send it to the REPL, see that it does what you want, then change the next function, and so on.

ClojureScript equivalents to GraphQL would be Om Next http://hueypetersen.com/posts/2016/02/13/om-next-from-a-rela... and and Posh with Reagent https://github.com/mpdairy/posh It's the same concept expressed in a Clojure idiomatic way.

I would highly recommend using Vim fireplace, Cursive, or Atom to start learning Clojure. Emacs is a very complex editor that takes a lot of time investment to be productive in. There's no reason to try and learn it while also learning Clojure. I've been developing Clojure professionally for the past 6 years and I've never used Emacs for that.

I appreciate your tip. However the error is still problematic that you can't find your stepping on what to fix.

Second, I can't embrace Clojure specific idioms that remove other platforms. That's why GraphQL is amazing, it standardizes across platforms for many types of clients. I embrace a polyglot engineering structure and there will be teams that use and consume GraphQL on languages outside of Clojure.

I'm comfortable with Emacs (just in VIM mode ;)).

Edit: to add, momentum is important in my eyes as well. It's hard to put down the momentum of GraphQL and it's adoption for something niche specific unless the pros heavily outweigh the current momentum. Which is definitely possible (why I'm investing this much energy to discover the viability of Clojure/Script/idioms) but I get very skittish when I see the current issues of community size, errors, and the lack of momentum compared to other technologies (Clojure looks like it's popularity has somewhat peaked unfortunately).

If a company/team can leverage Clojure and it's niches as a secret weapon despite it's smaller momentum then that's a huge win. But that means it has to be that big of a win compared to alternative technologies that do the same thing with a larger amount of people familiar with it.

Om next is not really Clojure specific, you could use the same query/transaction model in other languages as well. The server part is can be used with any database. As I understand, that is much harder with GraphQL.

Also more to your point on REPL - do you know of community docs of how to use the repl more effectively? I got the basics down but really want to see how a wizard does it.

I think if you only want to see how wizards do it, you'll have to fully master emacs. As a non-wizard and vim-forever guy, who only occasionally writes Clojure for hobby projects, here's my advice.

For a long time I got by with creating a split-screen terminal with 'screen', and then used vim-slime (https://technotales.wordpress.com/2007/10/03/like-slime-for-...). It doesn't have to be split, I just like it that way, but the idea is you have essentially two views talking to the same screen session. In one you launch a repl (with lein, or even a ruby/python repl if you want) and on the other half you open vim and type things like ctrl+c etc. to send fragments from vim to the repl.

More recently I've been using slimv (https://kovisoft.bitbucket.io/tutorial.html and https://github.com/kovisoft/slimv -- and if you want my three vimrc prefs http://pastebin.com/VjwrEJJQ) after using it for Lisp, which uses swank, and found I could also do some of this for Clojure's repl (https://github.com/technomancy/swank-clojure). Unfortunately it's kind of outdated, that's not where the community is going (and I haven't really bothered to figure out exactly where that is, though that project's readme gives hints, nor have I really tried Fireplace recently enough to say if I still dislike it). But it works for me, for now, unless I want to use ClojureScript. I'd say give it a shot, you might like it.

vim-fireplace is much improved. I had been using a heavily hacked version matched to my own preferences for years but recently upgraded.

What you really want is just to run

    lein repl 
in your repository and then fire up another terminal and edit code with Vim. Then you should send whole top-level forms to the repl with :Eval from Vim and it should just work. You can then test them in the repl. (I alias C-c C-c to :Eval (:no <C-c><C-c> :Eval<cr>) because I'm used to the old vim-slime)

And it should all work automatically. With the new versions of vim-fireplace it does just work automatically.

I'll write a 'process-data function in Vim, send it with :Eval, and then test it in the repl with (process-data {:some "data", :more "other data"}) and it all just works. There's a little reading up on namespaces necessary once your projects get complicated, but it works on a bare repl right out of the box, too.

With slimv I don't even have to run lein repl, it'll run it for me (well, 'lein swank') if it hasn't already so long as I'm somewhere with a project.clj. What I don't like about having my repl and editor separate is that it's harder to get or search values from the repl back into the editor. With slimv the repl is literally just another vim window/tile so it's easy to swap over, grab a value or search history, swap back, or enter interactive mode and type stuff.

Does vim-fireplace easily let you replace forms with values (or macroexpands) or evaluate a form and have its value put somewhere? By default slimv lets you save the expression you're evaluating (which is useful for testing things) but I think I'd have to set something custom up if I wanted it to store the value somewhere or replace the just-evaluated expression. If vim-fireplace did that out of the box I'd probably consider it again. I know emacs can do it, watching people perform/livecode with Overtone et al. is instructive.

Other things I appreciate about slimv are when I type "(defn " I see a nice helper below saying "(defn [name doc-string? attr-map... prepost-map? body) + attr-map?])", this applies to everything. If I type ",s" on any symbol it'll show me the (doc) for that symbol, ",h" takes me to the online clojure docs. When I type tab it auto-suggests core functions, presumably through standard omnicomplete features though. (Edit: another useful thing, I can simply trace/untrace function calls with ",t".) Does vim-fireplace support all/any of that out of the box? It sounds like it supports my "screen" flow just fine these days but what else does it give me?

A search for "clojure repl" on youtube will bring up lots of examples.

"I think some of your frustrations might stem from your workflow. You really have to use the REPL to get the most out of Clojure development."

Are there any good HOWTO, tutorial or documents that explain how? (ahh "clojure repl" on youtube) what about text? Looks like I'll search. One hint as to the maturity of a language ecosystem, is official docs that show these kinds of things.

Thanks for luminus btw.

I only use the repl for exploratory-figure-this-out type work. Once I have it figured out, I rewrite the function and reload the environment.

I find it is too easy to have a messed up environment (state) when tooling around with the repl.

Emacs is not complex at all, but it's easy to mess up if you don't do the C-h t tutorial and read the Emacs Lisp Intro. And if writing a couple lines of lisp to set up Cider is to difficult for someone, what will he do with Clojure?

The thing with Emacs is that it's a programming environment in which you're supposed to program. People want it to work like they want out-of-the-box, but that's like asking the Ruby interpreter to write your RoR application for you. With Emacs you don't reach median productivity on day one but maybe after a week or so, but then on your productiviry will increase and increase. But with other tools maybe you reach the median productivity on day one or two, but you stay thereabouts thereafter. And they eat up all your ram.

To say emacs is not complex is absurd. Still my favorite editor though.

I'd go further and say it's not complex, but rather complicated. In the same way that (forgive the example) the Vim command language is complex, but the Vim source code (gasp) is, well, very complicated.

I use Emacs (Spacemacs, so maybe that doesn't count!), though, and I'm willing to live with this if it means it can do what it does! :)

Spacemacs adds a whole lot of packages and subsystems, and a lot of complexity (layers, etc.). Emacs itself is really not complex if you take it as a programming environment. If you take it as an editor, and ignore its Lisp parts, then it's again not complex at all.

I went through the same pain points with GraphQL (to some extent I still do). I wound up writing a clojure wrapper around the Java GraphQL library, and that was a pretty easy endeavor, and got me farther along than the native library option. I keep telling myself to take time and open source it.

For the editor, I found a happiness with Atom + Proto REPL + Parinfer + Paredit (barely used). I wish I could get better integration with linting tools. I tried the vim approach for a while but Atom was way ahead in terms of REPL and Parinfer support. I'm not paying the cost to switch to emacs.

I'd note that Neovim is doing better with Parinfer support. Paredit seems okay with Vim, but you need guns/vim-sexp and tpope/vim-sexp-mappings-for-regular-people also to make the key bindings good. See my vim.info/.vimrc. [0]

[0] https://github.com/WildUtah/secret-personal-dotfiles/blob/ma...

Regarding GraphQL and Clojure, there's been a fair bit of experimentation around the Datomic Pull syntax, which performs a similar purpose. Om Next uses a variation of it, for instance.

I don't mean to trivialize any of the other concerns you mentioned, I just wanted to say that there is some uptake of GraphQL in the Clojure community. graphql-clj is one option, and I know of at least one other library being actively developed.

Isn't anything based on Om.next by definition based on graphql? That includes the Untangled framework.

Anything based on Om.next is inspired by graphql, not based on it.

For your concern number 3, the creator of spacemacs has created a package to help you author lisps in normal mode (https://github.com/syl20bnr/evil-lisp-state). It is included by default in spacemacs (all the bindings begining with `SPC k`).

It offers you all the cool features of paredit (barf, slurp, splice, transpose, convolute etc...), but it is easier to use in evil-mode. Check it out!

regarding #3, My philosophy with emacs and friends is not to try to learn too much. I have to confess that with paredit, all I know to do is slurp and barf (which sounds funny now that I've written it). I personally find the overhead of learning the jump around commands isn't worth the benefit to me.

I just use the vim aspect of spacemacs for efficient navigation.

Regarding #4, yeah. It is what it is... lein makes it all about twice as slow. 30 seconds sounds pretty crazy, but I don't do a lot with clojurescript. Most of my stuff will startup in about 5 or so seconds with lein, 3 without. even on a wimpy vps.

2. For me as well. I built a couple things with ClojureScript but once I started working with Relay and GraphQL I felt that it was no longer the best tool for the job.

Love seeing Clojure getting more usage and exposure. The more companies that use it, the more people will give it a chance, and it hopefully snowballs from there. Selfishly, this also means there's more of a chance I'll get to use it in my career.

It is easily the best language/platform I have used, and it is a joy to work with, Leiningen and Figwheel especially. Being able to use this wonderful language through the entire stack is a bonus. The drawbacks listed are real, but are getting better all the time. Spec goes a long way to improving error messages.

I think the docs have a lot to gain. If you take a look at https://clojuredocs.org/clojure.core/reify as an example, it's pretty much impossible to figure out what the heck reify does by reading that page.

That's not universally the case, but definitely a frustration. The examples are frequently the only way I can begin to figure out the usage of something at all (and they're typically the simplest-case example). I love examples in general, but it still speaks to the difficulty of parsing through some of those function documentations.

In the past I would have agreed strongly, but I have to say that in the last few weeks I've been diving back into Clojure, and the docs at clojure.org are much better than they once were. I like the structure of the "reference" sections, each of which dives into a single concept (e.g., multimethods). I agree, however, that the Getting Started guide is still very thin, and I dislike that the Clojure community seems to want very badly to make you learn emacs before you learn Clojure.


clojuredocs.org is just one community-powered docs site; there are several.

And that site has the exact same code-generated documentation, just with some different CSS. They just parse the clojure source. https://github.com/clojure/clojure/blob/f572a60262852af68cdb...

ClojureDocs isn't just generated documentation, but provides usage examples. Here's the page for reify https://clojuredocs.org/clojure.core/reify that illustrates the usage.

Yeah, that's the original page I linked, see my first comment. : )

Makes sense to see heavy usage in financial industry. Cognitect's Datomic database is perfect for the environment-datalog queries which work really well with time series data. Having an immutable audit trail of all atomic operation done on the database is taking the best out of what blockchain has been marketing.

It also seems like there's some demand to fund an open source version of Datomic:


Crowdfund open source Datomic alternative here:


NB: Datomic is not "append only" (when it was first released, I thought it was too):

  Note that accumulate-only is a semantic property, and is
  not the same as append-only, which is a structural 
  property describing how data is written. Datomic is not an
  append-only system, and does not have the performance
  characteristics associated with append-only systems.
Source: http://docs.datomic.com/indexes.html

I updated my original post to reflect that but I'm still not sure what the difference is.

A full open version would be a major undertaking.

What I've been thinking about about is step in the datomic direction, built on top of plain old postgres that wouldn't attempt full time travel, but would use the same general schema/model with history. It's seems crazy that in 2017 that we don't have a decent general option for most business apps to store facts that doesn't over-write the past as is done in current sql databases.

This project might be of interest actually https://github.com/datacrypt-project/hitchhiker-tree

This one that was posted here recently seems to be pointing in the right direction.


Absolutely. It's a huge undertaking which is why I think it's going to take a lot of crowdfunders to get one out the door.

It's not clear just how much of a demand there is for an open source alternative to Datomic which I'm trying to measure with the sign up landing page.

PostgreSQL solution might work if there was a way to guarantee immutable audit trail. This is really why Datomic favored in financial industries as it gives a high level of confidence that the audit trail can't be manipulated (even if you delete a record, that action will show up in the audit trail).

I do agree that it's rather surprising that we still don't have something like Datomic on github with a liberal licensing like MIT or BSD.

It could be due to demand or high cost barrier associated with emulating something like Datomic. And this is what I hope crowdfunding will change the game. Pay people to work on their pet project full time by crowdfunding it.

I have had some success stealing the immutability ideas out of Datomic and sticking them into normal RDBMs. I generally add a timestamp and a deleted flag to normal entities in the schema. Updates or deletes result in new tuples with later timestamps - in the case of deletes a "deleted" column gets updated to 'Y'. All read queries are actually executed against views defined on top of the entities where the max(timestamp) is used to select the most recent instance of an entity along with a check for deleted='N'. If the most recent tuple for an instance has been deleted, it won't show up in the results.

This actually works pretty well, but I have a REST API fronting the whole setup - programs are not directly accessing the underlying table or views directly.

> but I have a REST API fronting the whole setup

Have overheard of this in passing. Might elaborating on setup/use-case? Seems strange to me for someone to restrict themselves artifically and not expose the whole power of SQL etc..

Requirements were to allow internal and external teams the ability to CRUD a small set of resources using multiple programming languages, OS, and include command line scripting ability.

Direct access to our HIPAA/IRB database instances are based on white-lists - most internal and all external teams are prohibited from direct database connections. So for those groups, there is no possibility of any SQL access to schemas.

We use API keys with a shared secret (like AWS) to sign REST requests. If internal and external groups need to work together to jointly CRUD some resources for a specific project, they can share an API key dedicated to that project.

There was also a push to switch from an app-centric view of data management to an API-driven approach serving hypermedia (collection+json). That worked conceptually, but most API users ignore the embedded hypermedia links. I find that too bad, as those links make generic API consumption clients much more resilient to change - following a link embedded in a response rather than relying on POST to a well-known URI is a useful abstraction.

Sums it up - Clojure is ace, just needs better error messages, and Spec will sort that one out

Oh and Spec is a godsend.

> What has been most frustrating or has prevented you from using clojurescript more than you do now? The top answer here was "Using JavaЅcript libs with ClojureScript / Google Closure", which was a new choice we added this year.

Which the clojurescript compiler devs have addressed in recently released alpha features including extern inference: https://clojurescript.org/guides/externs

Is there a well maintained and high quality repository of third party externs, as there is in the form of DefinitelyTyped for typescript type definitions? Would such a thing subsume https://cljsjs.github.io/ ?

> Which the clojurescript compiler devs have addressed in recently released alpha features

Which the article mentions.

We have a node.js monolith that is currently being moved to AWS and split into microservices. Since I am the tech lead, I am in the position to decide that we are going to use Clojure where it makes sense; that is, everything that's being rewritten or added. Didn't regret it yet (and I think we won't later, either).

You might be interested in a project I started recently that's a port of the Ring stack to Node.js https://github.com/macchiato-framework/macchiato-core

My team is moving in the opposite direction with some of our services. We currently run everything on the JVM with Clojure, but now we're experimenting running some services using Node.js due to its lower footprint.

> This year we held steady in our response rate as 2,420 of you took the time

As a Clojure fan, I find the lack of growth a little disturbing. Why isn't it 20,000?

For the most part, because people don't answer multi-page surveys. :) We know that the number of respondents is only a fraction of the total number of users on any of the platforms where the survey was posted (Slack, reddit, mailing list, web sites, etc). 2015 was the first year we had an active Slack community (and it broke to HN that year for a bit) and that drove some increases. I would caution against trying to draw any hard conclusions just from the number of respondents.

As a long term Clojure user I have done this survey for years, but I don't think I did the last two times. Its just not that important anymore.

Whats the job market like for Clojure? Opinions and experiences please.

I am a Java developer by day and I fell in love with Clojure sometime ago. I have to give the language credit, because it taught me some new important concepts. After a break of couple of months (a year?) I went back to write some simple Clojure stuff - only to find out that the problem with error messages still persists: it's really easy to misuse some function here and there - especially if you don't use them on a daily basis - and sometimes tracking the actual source of the error/exception is almost impossible, even in a such developer-friendly IDE as Cursive. I can see how that can be absolutely discouraging for the beginners, even for people that are coming from Java backgrounds. Until that core problem is not fixed, it will never become a mainstream choice of a language.

The new spec library is being applied to clojure.core and will provide more precise errors at the point where an invalid value is introduced, rather than several layers down the stack.

You are right. It is a big problem. Its hard to do because you want to avoid complicated parsing and compilers. You don't want to put in lots of costume code.

Finally, I think the next version of Clojure will be able to make a big step. Spec improves multible problem points, error messages is one of them. It will take some time until the tooling around Spec is ready, but the data that spec provides is very nice for tools.

Curious if Clojure for CLR has tail call optimization given the CLR supports it?

Doubtful given it's built with C# which is pretty directly ported from the Java implementation.



i dont think clojure for clr is maintained much

The CLR port has been maintained and is up to date with the latest stable version of the JVM Clojure version. https://github.com/clojure/clojure-clr/blob/master/changes.m...

David Miller has been keeping it up to date for years, his efforts are not well enough appreciated.

Does anyone know, what the second most given answer for the question "What Clojure, ClojureScript, or ClojureCLR community forums have you used or attended in the last year?" is? The anwser is cut off.

Edit: typo

There is a link to the full results at the bottom of the article. That answer is "Clojure, ClojureScript, or ClojureCLR google group mailing list"


Oh, I missed that link. Thank you!

One of the things that always stops me pushing too far into clojure is memory footprint.

Does anyone have any suggestions or resources for how to keep the upfront memory cost of the jvm to a minimum (and monitor that its still within bounds over time).

128m is not acceptable, for my uses clojure would need to compete with go and rust which I can deliver 10-20m running in memory (and lightning fast).

I don't expect 10-20m but 10x doesn't work for me.

Think of deploying to Sandstorm.io as my goal ie small personal servers.

I'm working on a port of the Ring stack to Node.js for that exact reason. https://github.com/macchiato-framework/macchiato-core

I wrote about the motivation for the project in some detail here http://yogthos.net/posts/2016-11-30-Macchiato.html

You can see some example projects here https://github.com/macchiato-framework/examples

I've already ported some of my JVM services to it, and I've been very happy with the results. There's a Clojurians slack channel #macchiato where project discussions are happening, and others have been using it successfully as well.

I don't see Node.js as a replacement for the JVM, but it is a better fit for certain types of applications. Being able to develop Clojure using essentially the same stack on both platforms means being able to choose the right tool for the job.

I think it's really cool that you are pushing on this.

I'll probably pursue the jvm for a little while longer but I can see the attraction to clojurescript for this and will check in down the road.

With recent introduction of cheap high-RAM VPS and dedicated boxes like Scaleway, I don't feel this is a problem anymore. Running of Clojure on Java gives excellent multithreading environment - I personally don't want to sacrifice it for smaller memory footprint.

By default, the JVM will use all the memory you give it. Have you tried simply setting a small maximum heap size? You can use VisualVM to visualize the heap and GC. Deep monitoring is one of the JVM's greatest strengths.

Yes this was my thinking on how to proceed.

I'm just kind of surprised and disconcerted how little I could find on the web, specifically for minimizing footprint.

The JVM does not lack in documentation and advice; Clojure is riding on that.

You may be able to get there with AOT compilation and slimming down the JAR and JRE.

Is there a good Scheme-to-Clojure transpiler (to convert Scheme libs to Clojure libs)?

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact