TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Lisp: More is less

113 点作者 jobeirne超过 11 年前

27 条评论

gruseom超过 11 年前
This post repeats two memes that float around the programming language space. One is: &quot;it&#x27;s so powerful that it&#x27;s bad&quot;. The other is: &quot;it&#x27;s ok, but not for large projects&quot;. I don&#x27;t think I&#x27;ve ever seen any evidence attached to either. (If the OP contains any, I missed it.) But they&#x27;re the sort of things that sound plausible and have more gravitas than &quot;Here are my current preferences&quot;, so they get repeated, and no doubt the more they get repeated, the more they get repeated.<p>When I say &quot;evidence&quot; I&#x27;m not asking for formal studies; that&#x27;s too high a bar for our field. But one can at least ask to hear about specific real-world experience.<p>Of the two arguments, the &quot;too-powerful&quot; one has the disadvantage of being prima facie absurd, so I think the &quot;large-project&quot; one is more harmful. So, where are the large Clojure and Common Lisp projects that have been harmed by this alleged language weakness? Let&#x27;s find some practitioners who actually ran into this.<p>For what it&#x27;s worth, I haven&#x27;t. Since the best thing for a large project is not to be so large in the first place, applying language constructs to make codebases smaller is a great strength when the language lets you do it—and Lisp lets you do it.<p>Edit: [deleted off-topic bit]
评论 #7086079 未加载
评论 #7086184 未加载
6cxs2hd6超过 11 年前
&gt; <i>How can a static analysis tool keep up with a language that’s being arbitrarily extended at runtime? The prospect is daunting.</i><p>I don&#x27;t really understand that point. In Racket, for example, programs macro-expand down to a very small set of primitives, such as `let-values` and `lambda`. This makes it easier to do analysis, not harder. For example, this is how something like Typed Racket can support every idiom in untyped Racket programs -- because they all expand down to a fairly manageable core set of forms. (Or if you need to analyze something no-so-primtive, you can stop expansion on whatever that is.)<p>Racket is descended from Scheme. I don&#x27;t know if CL or Clojure expand down to quite such a small primitive core, but I imagine the story is roughly similar?<p>Anyway, writing such tools is not what the average programmer would do on a putative large project.<p>Any large project needs technical and social norms, mentoring, and leadership -- regardless of language. I think the language is the smallest part of it. Perhaps like how in security it&#x27;s social not technical engineering that usually turns out to be the weakest link.
评论 #7086047 未加载
评论 #7085987 未加载
评论 #7087645 未加载
swannodette超过 11 年前
Starting with &quot;Goodbye, static analysis&quot; it was pretty hard for me to take this article seriously. Macros <i>desugar</i> into primitive forms - this means most macro language extensions are amenable to static analysis! Clojure has Kibit, Eastwood, and Typed Clojure (a whole type system via ... macros!) for static analysis. In addition Clojure and ClojureScript now both have fairly powerful analyzers that catch bad style and errors today and can be extended to do even more.
评论 #7087798 未加载
nnq超过 11 年前
Good arguments for why Python is a great little language, but no convincing ones regarding Lisp: there are no large software projects undertaken in Lisp recently (or ever?) that have failed <i>because</i> of it&#x27;s extreme flexibility making collaboration impossible, no lisp programmers complain that there are too many ways of doing things or about &quot;conceptual clutter&quot; (ok, after my encounter with CL I&#x27;d complain about it, but I never got any real work done in CL so my opinion doesn&#x27;t matter - maybe the &quot;conceptual clutter&quot; would&#x27;ve ended up to be &quot;invaluable expresivity&#x2F;flexibility&quot; in a real world project) etc.
weavejester超过 11 年前
Macros are used quite rarely in Clojure. In general they swing between two extremes, either as a means of providing some simple syntax sugar, or as what effectively amounts to a language extension.<p>The author cites Korma as an example of a library that uses macros, but Korma only uses macros to provide a small degree of syntax sugar. So instead of writing:<p><pre><code> (exec (where* (select* people) `(&gt; :age 18))) </code></pre> One can instead write:<p><pre><code> (select people (where (&gt; :age 18))) </code></pre> It&#x27;s an extremely simple transformation, and can be expressed in a few lines of code.<p>There are some libraries, such as core.async or core.logic, that make more extensive use of macros, but these libraries are relatively rare, and take a lot of work to get right. It&#x27;s something I&#x27;d expect to see in a dedicated library, not as part of a solution in a large software project.<p>Worrying about overuse of macros in Clojure is a bit like worrying about overuse of FFIs in Python. Sure, it&#x27;s possible to abuse in theory, but it&#x27;s not really a problem in practise.
rcarmo超过 11 年前
The OP is going to have kittens when he finds out about hylang (<a href="https://github.com/hylang/hy" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;hylang&#x2F;hy</a>)
评论 #7086307 未加载
评论 #7085990 未加载
drblast超过 11 年前
What I value most in a programming language:<p>1. I&#x27;m able to concisely express what I&#x27;m trying to do.<p>2. I never, <i>never</i> have to copy&#x2F;paste or otherwise do repetitive work because one case is slightly different than another.<p>Number 2 is probably more important to me. It&#x27;s why I&#x27;m happy when a language has first class functions and closures, and why I&#x27;m unhappy when the language is Java.<p>I think the cases where you can&#x27;t modularize things enough such that you have to essentially include two version of the same thing is a programming language expressiveness failure.<p>Finally, I strongly disagree that programmers aren&#x27;t or shouldn&#x27;t be language designers. Nearly every worthwhile program I&#x27;ve written that people have used has needed an API or scripting&#x2F;query language. So any language had damn well be suited to writing a parser. LISP fills that bill too.<p>If LISP has shortcomings, its expressiveness and power are not them. If you want to complain about a lack of consistent implementations, lack of libraries, difficulty interoperating with any other language, lack of a canonical free implementation, no decent supported GUI toolkit, or the impossibility of distributing binaries real people can use without spending thousand of dollars on a professional LISP environment, go right ahead.
mildtrepidation超过 11 年前
[edit: While I was typing this the title was changed. It was previously <i>Why Lisp isn&#x27;t (and shouldn&#x27;t be) widely used in industry</i>, which colors my comment.]<p>This points out some very real potential dangers of large-scale collaboration with Clojure (and presumably some or many other Lisps&#x2F;Lisp-likes).<p>However, I think the conclusion is overstated. Yes, based on what&#x27;s provided, it may take more discipline and better, more explicit processes for a team to effectively collaborate in Clojure than in Python (using the author&#x27;s running comparison). Yes, if we take this at face value, it does appear that people who depend on static analysis might find Lisp lacking.<p>But does this tell us why Lisp isn&#x27;t widely used in industry? If we assume that &quot;widely&quot; means &quot;as widely as Java or Python,&quot; which seems to be the statement made here, I don&#x27;t think it&#x27;s valid to cite the provided complaints as most or even a large portion of the explanation. The fact that there are no or almost no mainstream educational institutions teaching new students Lisp seems to me a far more likely candidate for front-runner on this issue.<p>That it shouldn&#x27;t be <i>widely</i> used is a little easier for me to agree with, only because I&#x27;m on board with some of the points here about the discipline and extra work it would take for a large team to effectively cooperate given the malleability of Lisp. I&#x27;ve worked with enough other programmers to know that kind of care and attention to process are very rare (and this isn&#x27;t &quot;all of you suck;&quot; I know I have and will again cut corners and ignore protocol in situations where time or resources make it hard to do things perfectly every time).<p>Also, I think the author&#x27;s last point is important to mention, because it&#x27;d be easy to miss it: He&#x27;s not arguing that Lisp sucks. He states explicitly that it&#x27;s great in at least some ways. I just don&#x27;t think the black and white claims being made about its practicality are quite supported.
评论 #7086135 未加载
robertjflong超过 11 年前
Don&#x27;t fear the macro!<p>&quot;Lisp isn&#x27;t a language, it&#x27;s a building material&quot; - Alan Kay.<p>Lisp is an opportunity to build a DSL that fits any given problem domain elegantly.
lkrubner超过 11 年前
Most of the complaints in this article boil down to &quot;macros are too powerful.&quot; I think this is the key part of the argument:<p>&quot;A smart programmer is not necessarily an empathetic language designer; they are occupations that require different skillsets. Giving any programmer on your team the ability to arbitrarily extend the compiler can lead to a bevy of strange syntax and hard-to-debug idiosyncrasies.&quot;<p>There are at least 2 counter-arguments to this:<p>1.) in the simplest case, just restrict the use of macros. A team can easily adapt the rule that only the most experienced engineer on the team is allowed to write or approve macros. (And in my experience, the need for macros is fairly rare. I think my ratio is something like 100 or 200 normal functions for every macro that I write.)<p>2.) macros allow all kinds of interesting type checking, and data structure validation, and therefore they make it surprisingly easy to validate data and types as your data and&#x2F;or vars get passed around your system. Consider all of these very interesting tools you can use in the world of Clojure:<p>Prismatic Schema which allows validation that a data structure matches a schema of (possibly nested) types:<p><a href="https://github.com/prismatic/schema" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;prismatic&#x2F;schema</a><p>and this now offers coercion, which makes this fantastic for importing JSON from other sub-systems or outside vendors:<p><a href="http://blog.getprismatic.com/blog/2014/1/4/schema-020-back-with-clojurescript-data-coercion" rel="nofollow">http:&#x2F;&#x2F;blog.getprismatic.com&#x2F;blog&#x2F;2014&#x2F;1&#x2F;4&#x2F;schema-020-back-w...</a><p>(I assume you could easily validate before giving data to Liberator to export your data while conforming to your schema: <a href="http://clojure-liberator.github.io/liberator/" rel="nofollow">http:&#x2F;&#x2F;clojure-liberator.github.io&#x2F;liberator&#x2F;</a> )<p>There is work being done on an optional type system:<p><a href="https://github.com/clojure/core.typed" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;clojure&#x2F;core.typed</a><p>Much effort has been made to make contract programming easy in Clojure:<p><a href="https://github.com/clojure/core.contracts" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;clojure&#x2F;core.contracts</a><p>But also I find the built-in syntax for writing pre and post assertions is clean and easy to use:<p><a href="http://blog.fogus.me/2009/12/21/clojures-pre-and-post/" rel="nofollow">http:&#x2F;&#x2F;blog.fogus.me&#x2F;2009&#x2F;12&#x2F;21&#x2F;clojures-pre-and-post&#x2F;</a><p>In short, there are an abundance of mechanisms available with Clojure which help facilitate the enforcement of any kind of schema or contract, and some of these tools are enabled (and their syntax is made clean) thanks to macros.<p>In short: macros can be used for evil, but they can also be used for good. They are very powerful, so everyone should be judicious about their use, but there is no reason to argue that macros render a Lisp unfit for programming in the large.<p>Having said all that, I&#x27;ll remind everyone that the ultimate counter-argument is offered by Paul Graham, in his essay &quot;Beating the averages&quot;:<p><a href="http://www.paulgraham.com/avg.html" rel="nofollow">http:&#x2F;&#x2F;www.paulgraham.com&#x2F;avg.html</a><p>If that essay does not convince you of the value of macros&#x2F;lisp, then nothing will.
评论 #7086093 未加载
评论 #7086074 未加载
评论 #7087434 未加载
评论 #7088974 未加载
评论 #7085949 未加载
stuhood超过 11 年前
I wasn&#x27;t excited about scala&#x27;s macros initially [a], but Eugene&#x27;s Burmako&#x27;s recent talk [b] on the constraints the developers worked with to keep macros consistent and interoperable was illuminating, and has changed my mind to a large degree [c].<p>In the end, they only directly added support for 1) type-safe macros, aka &quot;black-box&quot; macros 2) ...invoked transparently as methods, aka &quot;def macros&quot;<p>They identified &quot;white-box&quot; (non-type safe) macros and quasiquoting as distinct from black-box macros, because the type signature of a black-box macro tells you approximately what it will do, meaning that you can treat it as a &quot;black box&quot;. But additionally, in order to write a meaningful type signature, the input to a black-box macro must _already_ be valid scala code! This means that the addition of macros cannot actually result in new scala syntax [d].<p>[a] <a href="https://news.ycombinator.com/item?id=3709193" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=3709193</a><p>[b] <a href="http://www.infoq.com/presentations/scala-macros" rel="nofollow">http:&#x2F;&#x2F;www.infoq.com&#x2F;presentations&#x2F;scala-macros</a><p>[c] still hoping the existence of scala macros leads to the deprecation of a bunch of other features though<p>[d] see the explanation starting around 33m30s in [b]
nonrecursive超过 11 年前
I remember seeing the same kind of arguments about Ruby when it began to become popular. &quot;Ruby is too dynamic. You shouldn&#x27;t use it on large-scale projects.&quot;<p>Learning a language involves more than just learning syntax and semantics. You also need to learn how to write for maintainability. It sounds like the author is less certain about how to do that with Lisp, but instead of seeing it as a chance to learn more he writes off the entire Lisp family as impractical.
评论 #7089065 未加载
m0skit0超过 11 年前
&quot;OOP is widely-used and easily comprehended because it is a fairly simple way of modeling reality that is compatible with how human beings do it&quot; I don&#x27;t see how OOP is &quot;fairly simple&quot;, &quot;modeling reality&quot; and &quot;compatible with how beings do it&quot;. How inheritance, polymorphism, interfaces, classes, objects, types is a &quot;simple&quot; model of reality? You&#x27;re simply used to think OOP way, that&#x27;s all.
lispm超过 11 年前
If I had the choice to develop a functionality as a Lisp macro or alternatively as an XML-based DSL for Java, I would know what I&#x27;d prefer...
rtpg超过 11 年前
Haskell, by its lazy evaluation, is basically a macro-only language, and people seem to be doing fine in that end of the world.<p>Granted, space leak issues are pretty difficult to analyse, so it makes the language seem hard to use in practice, but that&#x27;s because all the low-hanging fruit like type errors are solved by how the language is designed, so you only end up with the hard bugs.
评论 #7091444 未加载
评论 #7086192 未加载
r-s超过 11 年前
A large reason there is fewer large lisp projects, is that its pretty hard to get a team of lisp developers. Also, many programmers who do know languages like a lisp or Haskell are often going to be better programmers and will require a higher salary. Not everyone who codes in these languages is a great programmer, but I suspect there is some correlation.
评论 #7085978 未加载
Patient0超过 11 年前
&quot;OOP is widely-used and easily comprehended because it is a fairly simple way of modeling reality that is compatible with how human beings do it.&quot;<p>I disagree with this. Ask any non-programmer &quot;is a square a rectangle?&quot; Or &quot;is a list of triangles a list of shapes?&quot; and they will say &quot;Yes!&quot;<p>Yet as soon as either of these becomes mutable it all falls apart and intuition fails. You cannot change the height of a square independently of its width, you cannot add a square to a list of triangles (but you can add a square to a list of shapes).<p>Human beings reason &quot;immutably&quot;.<p>&quot;Fine only do OO with immutable objects!&quot; I hear you say. It&#x27;s a good idea buy you&#x27;re now on the path (that I took a few years ago) towards functional programming.<p>This is why I think that OO, and more particularly mutable state, are quite difficult for new programmers to grasp.
fleitz超过 11 年前
The biggest problem with LISP is the lack of large organizations who use it.<p>C has all these problems as do C++, Java, Python, Ruby.
评论 #7085955 未加载
wwkeyboard超过 11 年前
As a tangent, we still don&#x27;t have a good definition of &#x27;large&#x27; software project. Clojure hasn&#x27;t been around for 8 years, so we don&#x27;t have 10 or 15 year projects to look at. And I think we&#x27;d have heard if there was a 1500 developer team using it. It sounds absurd, but there have been plenty of projects this size and they &#x27;work&#x27; insomuch as they generate enough revenue the sponsoring companies paid for them to get that size.
cuyoman超过 11 年前
I think the designers of Clojure intend it as a language for experts. In many fields non-experts can make nice progress, but they need to be aware that they may stub their toes. So, pull requests, code reviews, pairing, etc. are available and well established as means for helping people make the transition from beginner to journeyman (person) and beyond. If I know how to walk, but not how to ride a bike, I hardly think others should be denied nice bike routes.
nickik超过 11 年前
&gt; OOP is widely-used and easily comprehended because it is a fairly simple way of modeling reality that is compatible with how human beings do it.<p>Have we not learn by now that these systems are not easy to reason about. Are not all the things one first learns (ie Animal -&gt; Dog) bullshit and should be avoided.<p>Why is it in every good OO book that, composition is better then inheritance. Why is every OO book full of examples about how to avoid mutabiltiy and make the system easy to reason about?<p>The idea that OOP systems (as generally) thougth of goes completly out of the window as soon as you have any kind of concurency, even just event handling.<p>&gt; which rejects OOP<p>It does not reject, it takes the usful features like polymorpism and gives them to you. Protocols are better then interfaces, better then duck typing.<p>&gt; In Clojure, if I want to define a symbol there are nine different ways of doing so.<p>There are a lot more then nine. But I would recomend rich or stus talks on simple vs easy. Just saying there is nine of something and thus its complicated is idiotic.<p>Java has only one thing, classes, does that make it simply, or does that just mean that its hoplessly overloaded?<p>Clojure is extreamly simply. State can only live in a var, atom, ref or agent. Every one of these has clear semantics, this includes clear sematnics in a multithreaded world. No other language has such clearly defined state management.<p>&gt; Clojure claims to include these language features as a way to mitigate the complexity of parallelism; frankly, I’ve never found threading or interprocess communication to be any sort of conceptual bottleneck while working on some fairly complex distributed systems in Python.<p>Distributed system != Shared Memory<p>Nobody, really nobody can say taht distributed systems are easy. Just listen to the people that implment this stuff. But it is clear that a language generally does not really help you with reasoning about that system.<p>However when you run on a 16 core with shared memory and you have to do lock ordering and all this stuff,then you will defently be happy for the tools that clojure provides.<p>&gt; Less is more (as long as “less” is sufficiently convenient).<p>Clojure is actually a much smaller and much simpler langauge then python every can hope to be. Clojure is simple, and strives for simplicity in every feature of the langauge. See here:<p>- Simplicity Ain&#x27;t Easy - Stuart Halloway <a href="http://www.youtube.com/watch?v=cidchWg74Y4" rel="nofollow">http:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=cidchWg74Y4</a><p>- Simple Made Easy <a href="http://www.infoq.com/presentations/Simple-Made-Easy" rel="nofollow">http:&#x2F;&#x2F;www.infoq.com&#x2F;presentations&#x2F;Simple-Made-Easy</a>
评论 #7087903 未加载
评论 #7086056 未加载
Myk267超过 11 年前
This is just fuel in search of fire.<p>&quot;OOP is widely-used and easily comprehended because it is a fairly simple way of modeling reality that is compatible with how human beings do it.&quot;<p>Close, but no pants, Buckwheat!
arthuredelstein超过 11 年前
You don&#x27;t find large-scale Clojure projects, because Clojure is very concise.
评论 #7087803 未加载
slantedview超过 11 年前
Using a Lisp does not necessarily preclude static anlysis.
aufreak3超过 11 年前
I don&#x27;t find the arguments against macros workable since the emergence of syntax transformation while modeling a problem shows many deep relationships between parts of the domain .. in the cases I&#x27;ve seen. Just want to share some stuff that I haven&#x27;t seen others write about.<p>I don&#x27;t code much lisp these days (though getting into clojurescript a bit now), but when I used to, the cycle went pretty much like this -<p>1. Express what you want to express as an s-expression, capturing known structures in the simplest way I can think of.<p>2. Figure out which aspects can be &quot;functions&quot; straight forwardly and which are macros and implement them.<p>3. Test and iterate a bit till I like the way domain elements are composing and the way the composition looks in code. Try to reduce the required concepts in each iteration.<p>4. Document the relationships that have emerged from this process so others can understand it.<p>5. Usually I&#x27;m done, but sometimes (the few) users of my &quot;api&quot; come back with questions, based on which I iterate a bit more.<p>I&#x27;ve mostly followed this in building the &quot;editing style specification language&quot;[1] part of the product &quot;muvee Reveal&quot; (an automatic video editor)[2], built in a custom scheme dialect called &quot;muSE&quot;[3]. (Full disclosure: I&#x27;ve happily worked for muvee Technologies from 2002 to 2011.)<p>Btw - most discussion on macros and lisp seem to first assume that there two things - a) functions and b) macros. There are more, depending on the kind of lisp system you&#x27;re working with.<p>You could form a taxonomy of sorts based on whether argument forms are evaluated and whether the result form is evaluated -<p>1. Argument forms are evaluated before &quot;apply&quot;, result is a value (i.e. not evaluated). =&gt; Function<p>2. Argument forms are unevaluated before &quot;apply&quot;, result is code (i.e. is evaluated). =&gt; Traditional macro<p>3. Argument forms are evaluated before &quot;apply&quot;, result is code (i.e. is evaluated).<p>4. Argument forms are unevaluated before &quot;apply&quot;, result is a value. =&gt; Traditional macro (depending on system)<p>In the course of using the domain modeling approach above, I&#x27;ve written stuff like functions that create one or more macros, macros that evaluate to function values (not s-expressions) and such stuff that might be considered an &quot;abomination&quot; by the OP ... but in the context of the domain, the <i>concepts</i> are usually clear enough to be used without major issues.<p>[1]: <a href="https://code.google.com/p/muvee-style-authoring/" rel="nofollow">https:&#x2F;&#x2F;code.google.com&#x2F;p&#x2F;muvee-style-authoring&#x2F;</a> [2]: <a href="http://www.muvee.com/en/products/reveal" rel="nofollow">http:&#x2F;&#x2F;www.muvee.com&#x2F;en&#x2F;products&#x2F;reveal</a> [3]: <a href="https://code.google.com/p/muvee-symbolic-expressions/" rel="nofollow">https:&#x2F;&#x2F;code.google.com&#x2F;p&#x2F;muvee-symbolic-expressions&#x2F;</a>
innguest超过 11 年前
The author of the blogpost is pretending to be &quot;one of us&quot; (people that get lisp) - in &quot;Lisp devotees (myself once included)&quot; - but apparently they never understood it if they&#x27;re still thinking that lisps&#x27; advantages &quot;make Lisp into an unweidly, conceptual sledgehammer that’s often out of scale with the problem being solved.&quot;. The word &quot;often&quot; there also makes me think they&#x27;re making a point without experience or proper evidence.<p>They&#x27;re a lisper who broke their teeth in Clojure. I think when people like me disdain Clojure&#x27;s lispness is because we think it doesn&#x27;t really teach you the philosophy behind it. This is not an argument, just my perception.<p>They&#x27;re also in favor of code censorship (let&#x27;s remember that censoring is detrimental to creative processes):<p>&quot;Giving any programmer on your team the ability to arbitrarily extend the compiler can lead to a bevy of strange syntax and hard-to-debug idiosyncrasies. &quot;<p>I use Racket in production along with my team and may I suggest a humble, easy solution: one person makes a pull request, another reviews the pull, and if there are new macros introduced we can discuss it with the team to see if it&#x27;s necessary. It&#x27;s so simple. The blogpost author is making a big deal out of nothing. To prefer a language that doesn&#x27;t allow that power because the author has a problem trusting others instead of choosing to communicate with their team members is appalling.<p>The author also keeps mentioning Python&#x27;s &quot;simplicity&quot;. How can anything be as simple as (function args)? I&#x27;m yet to understand what people that argue this point mean by &quot;simplicity&quot;.<p>Then the author talks about static checks. &quot;How can a static analysis tool keep up with a language that’s being arbitrarily extended at runtime?&quot;. Simple, do macro expansion before static type checking, as Typed Racket does.<p>They&#x27;re also still playing with SQL DSLs too. I think that&#x27;s such a waste of effort. SQL is already a DSL for talking to the DB. I don&#x27;t want another layer because I&#x27;m not going to be manipulating SQL in my code, because &quot;SQL&quot; has nothing to do with the problem domain I&#x27;m working on. At that point any SQL queries have already been abstracted away inside functions that have meaningful names like associate-product-to-customer or whatever. I don&#x27;t want to talk about SQL ever in my problem domain abstraction layer. Using SQL DSLs as an argument against macros with the angle of static type checking is a poor argument because SQL DSLs are usually for people that use mutable code anyway. I use Typed Racket&#x27;s DB library and its querying functions work together with the type system to let me know if I&#x27;m not handling some potential kind of value that might come from the database.<p>The author then mentions Unix&#x27;s consistency. Unix couldn&#x27;t even decide on a standard notation for command line arguments. Then onto that fallacy that reality is object-oriented. Objects can&#x27;t possibly be as composable as functions because Objects break down into methods (which are not composable, are not first class, etc) whereas functions (lambdas) can make up everything and can really be thought of as an atom for computation (i.e. Lambda Calculus).<p>Complaints like &quot;Clojure has nine different ways to define a symbol&quot; are moot. Pick one that your team likes and go with it. On to the next thing. Also, to argue against Lisps by arguing against Clojure is like arguing against democracy by arguing against the Democratic Republic of the Congo.<p>I do believe the blogpost author is severely misguided in their criticism. To say things like &quot;Python wants the conceptual machinery for accomplishing a certain thing within the language to be obvious and singular&quot; while ignoring the fact that lisps machinery is obviously much simpler and obvious and singular - again, (function args) - is disingenuous. It does make me believe that all their SICP reading was for nothing (I&#x27;ve only lightly skimmed SICP and I don&#x27;t pretend to have read it).<p>The author does acknowledge (en passant) that certain Schemes (they don&#x27;t identify which) don&#x27;t suffer from this complexity (which makes the whole post look more like a criticism of Clojure). I&#x27;d invite the author to look into Racket.<p>They say that lisps &quot;impose significant costs in terms of programmer comprehension&quot;. My experience is that if you divide your layers of abstraction correctly you will be able to work in the problem domain layer where nothing is obscure. And that layer is built from smaller in the layer below, parts that are also clear in what they accomplish because they only do one thing in their abstraction level. I&#x27;ve found that following this rule of only doing one thing per function makes for code that is easy to understand all the way from the bottom to the top layers. Programming this way, however, is the classic, boring way to write code [1], and because it&#x27;s not a fad I guess people aren&#x27;t too much into it.<p>Also to the point above, having already rewritten a significant portion of a Rails legacy app into Racket with the help of my coworkers, it seems that lisps introduce more understanding and shed more light onto the code, precisely because it makes everything explicit (we code in functional style so we pass every argument a function needs) and does away with &quot;Magic&quot; that Rails and rails fans like so much. When something gets annoying to write we implement our own &quot;magic&quot; on top of it, not in terms of silly runtime transformations that lesser languages like Ruby need to resort to, but through dynamic variables (Racket calls them parameters), monadic contexts, etc, i.e. things that can be checked at compile time.<p>And finally: &quot;I think it’d be irresponsible to choose Lisp for a large-scale project given the risks it introduces&quot;. Well, the only risk I&#x27;ve personally witnessed is the very real risk of your coworkers starting do dislike more mainstream, faddish languages like Python and Ruby, because they don&#x27;t allow the same freedom and simplicity and explicitness that lisp does (lisp has a long tradition of making things first-class, which consequently makes these things explicit).<p>[1] We use top-down design to decide what the interface for a given abstraction layer will look like, and bottom-up to decide which functions should be written in the layer below; then we cycle that process by refining the layer below through the same process of defining its interface top-down and then the layer below it as bottom-up. And we use algebraic type checking along with contracts to enforce post-conditions and properly assign the blame to the right portion of the code to speed up debugging. These are all old techniques.
评论 #7086652 未加载
评论 #7087978 未加载
评论 #7086313 未加载
dschiptsov超过 11 年前
A lot of confusion comes from regarding Clojure as a Lisp (in my opinion, to call Clojure a Lisp is the same fallacy as to call Ruby a Smalltalk) and especially thinking that Clojure is &quot;what a Lisp should be&quot;.<p>On the contrary, beauty of Lisp comes from being accidentally discovered minimal set of unique interweaving features (very few special forms, high order procedures, list structure, to glue code and data together, macros, the way to use Lisp as a meta-language to itself, type-tagging of values, instead of declaring variables, and, the numeric tower, and lexical scooping, as recent addirion).<p>This set of features is very balanced and good-enough. Adding more &quot;foreign&quot; features actually ruins the balance.<p>Having &quot;just this&quot; and following the paradigm of layered DSLs embedded in a Lisp, popularized by SICP, lots of complicated things could be created, including CLOS which is nothing but a DSL (a bunch of macros and procedures).<p>This notion of what a Lisp is actually helpful to understand not just Clojure but also Haskell, which is, in some sense, also a small kernel based on Lambda Calculus and tons of syntactic sugar.<p>By adding more and more features without breaking the balance we got Common Lisp, while an attempt to keep the balance produced R5RS.<p>If we switch the perspective on what Clojure is to the notion of a scripting language for the JVM (a-la Ruby) with sometimes looks like a Lisp and sometimes behaves like a Lisp, but strictly speaking not a Lisp, because the unique balance was ruined by adding stuff, everything, it seems, falls into its places.<p>Arc is a dialect of Lisp, Clojure is language of its own, but marketed as a &quot;modern dialect of Lisp&quot;, which makes no sense.
评论 #7087421 未加载