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

科技回声

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

GitHubTwitter

首页

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

资源链接

HackerNews API原版 HackerNewsNext.js

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

Clojure vs. Scala

129 点作者 iamtechaddict超过 11 年前

25 条评论

lmm超过 11 年前
Scala guy here<p>Suits would surely be case objects rather than classes, or I&#x27;d be tempted to just use a Java enum (Scala could really do with an equivalent). With card ranks, either you want to be able to compare them - in which case integers are the correct representation - or they&#x27;re just 13 &quot;things&quot;, in which case again an enum-like representation is good; I can&#x27;t imagine why you&#x27;d ever want to represent a card rank as int-or-string.<p>Case classes are java-serializable by default. Any number of other serializers (json, database...) exist that work seamlessly with case classes. I do think it would be nice to have an abstraction for something weaker than a class, something that was guaranteed to be inert data, but still typed.<p>And yeah, I might implement a deck as something that contains a sequence. But I could then derive typeclasses for sequence operations quite cheaply using lenses. (I do wish there was a nicer way of doing this kind of delegation though).<p>Sure, Scala steers you towards making a type straightjacket for yourself; you definitely can operate on stringly typed or maply typed data, as it sounds like Clojure encourages you to do all the time. And maybe it&#x27;s not the best language for exploratory manipulation of semi-structured data. But when the time comes to write a production-ready system, the strong types that Scala gives you are a much faster way to achieve the level of reliability you need than the level of testing you need in a less typed language.<p>(And even if you don&#x27;t need the safety, I find types are a great aid to figuring out WTF you were doing if you come back to the code in six months&#x27; time)
评论 #6959229 未加载
评论 #6959171 未加载
octo_t超过 11 年前
So the Scala solution for this is: <a href="http://ideone.com/Vussjh" rel="nofollow">http:&#x2F;&#x2F;ideone.com&#x2F;Vussjh</a><p><pre><code> object Cards { sealed trait Suit case object Spades extends Suit case object Clubs extends Suit case object Hearts extends Suit case object Diamonds extends Suit sealed trait Rank trait FaceCard extends Rank case object Jack extends FaceCard case object Queen extends FaceCard case object King extends FaceCard case object Ace extends FaceCard case class ValueCard(n: Int) extends Rank case class Card(rank: Rank, suit: Suit) type Deck = IndexedSeq[Card] def numberToRank(n: Int): Rank = n match { case 1 =&gt; Ace case x if x &lt;= 10 =&gt; ValueCard(x) case 11 =&gt; Jack case 12 =&gt; Queen case 13 =&gt; King case 14 =&gt; Ace case _ =&gt; throw new IllegalArgumentException } def numberToSuit(n: Int): Suit = n match { case 0 =&gt; Spades case 1 =&gt; Clubs case 2 =&gt; Hearts case 3 =&gt; Diamonds } def apply(): Deck = for(rank &lt;- 1 to 13; suit &lt;- 0 to 3) yield Card(numberToRank(rank), numberToSuit(suit)) } </code></pre> Now I have: normal operations bound to Deck (head, take, drop etc) and the ability to pattern match on cards. Also strongly typed. This took about 5 minutes top to write.<p>edit: I&#x27;d say the &#x27;numberToRank&#x27; parts are probably code smells, but given that its Christmas Eve, I really can&#x27;t be bothered to think of a better solution right now. Implementing ordering etc can be done on the traits very easily too, but that is game specific (for example are aces high or low, is a King ranked higher than a Jack etc).
评论 #6959346 未加载
评论 #6960950 未加载
adrianm超过 11 年前
I think people here are totally missing out on appreciating a very thoughtfully written post by focusing on the fact that he may be comparing programs written in his favorite language to your favorite language. He is not asking for Scala solutions to any problem - and he has not contrived a deceptive Scala solution to &quot;prove&quot; the superiority of his language of choice.<p>He&#x27;s comparing the structure and design of programs between two great languages of similar capabilities (features) and philosophies. I think his point about lightweight data modeling is spot on - Clojure is a language that goes out of its way to make modeling your problems idiomatically painless and dramatically simpler than most other languages.<p>It&#x27;s idiomatic in Clojure to use plain old maps to represent structures or entities in your program that you would otherwise represent with a class or equivalent construct in many Object Oriented languages. That isn&#x27;t a code smell either - it&#x27;s idiomatic and wonderful. Keywords (similar to Ruby symbols in both use and philosophy) are wonderful things that together with maps make enums as a language primitive irrelevant.
评论 #6959873 未加载
pixelmonkey超过 11 年前
Sounds like idiomatic Clojure has more in common with Python than it does with Java. I&#x27;m finding that to be true as I teach myself Clojure. My background is an ex-advanced-Java programmer who left that all behind and has built production systems in Python for the last ~5 years. I&#x27;m learning Clojure now because the Java ecosystem is important to me, but I simply refuse to use Java to interact with it :)<p>Lightweight data modeling is important and Java is truly terrible at this. I illustrated this in a gist about creating and iterating over a list and a map, and contrasting that to the equivalent Python: <a href="https://gist.github.com/amontalenti/8114359" rel="nofollow">https:&#x2F;&#x2F;gist.github.com&#x2F;amontalenti&#x2F;8114359</a><p>The author says about Scala: &quot;Due to its highly detailed static type system, Scala attracts the kind of programmers that like to carefully categorize and enumerate all the possible data structures.&quot;<p>It turns out, this describes expert Java programmers very well, too -- so it&#x27;s no surprise that Scala is a very popular language with Java programmers. I&#x27;m finding that Clojure is the more attractive language if your sensitivities lean toward the &quot;simplicity&quot; and &quot;dynamism&quot; camp. I was reading some Scala code being used in production at Twitter and found this marvel: <a href="https://twitter.com/amontalenti/status/410977749629546496" rel="nofollow">https:&#x2F;&#x2F;twitter.com&#x2F;amontalenti&#x2F;status&#x2F;410977749629546496</a> -- you would simply never see anything like this in Clojure or Python codebases.<p>The point about multi-paradigm is interesting. It&#x27;s very true that Clojure, unlike Python, does not support true multi-paradigm. Then again, Python does not support &quot;true&quot; functional programming. It&#x27;s close, but no cigar, due to the lack of full-featured lambdas &#x2F; blocks. If you have to pick one paradigm, functional is definitely the simpler and more essential one.<p>Illustration: imagine a variant of Python that forced all code to live in classes -- ick. But imagine a variant of Python without classes -- that&#x27;s not so bad.<p>It&#x27;s worth reading about Clojure&#x27;s take on object-orientation-atop-functional using multimethods and hierarchies: <a href="http://clojure.org/multimethods" rel="nofollow">http:&#x2F;&#x2F;clojure.org&#x2F;multimethods</a>
评论 #6959751 未加载
评论 #6959714 未加载
评论 #6959909 未加载
评论 #6959846 未加载
评论 #6960140 未加载
hythloday超过 11 年前
I actually had something similar a couple of weeks ago. My initial model was just:<p><pre><code> val cards = for { rank &lt;- &#x27;a, &#x27;2, [...], &#x27;j, &#x27;q, &#x27;k suit &lt;- &#x27;h, &#x27;c, &#x27;d, &#x27;s } yield (rank, suit) val deck = scala.util.Random.shuffle(cards) </code></pre> which gives you something to play with to validate your model. It&#x27;s not an api I&#x27;d choose to publish, of course, there are many better type-safe ones written here, though I&#x27;m sad none of them have used Unicode for suits (I know someone working on a dating app who used a method called ❤ to compare two users: so something like &quot;if (sappho ❤ rhodopis &gt; 95) { ... }&quot;)<p>But my point is that Scala gives you the option, and is tolerant, of working in this slightly dirty way, and then lets you clean it up (and a type-safe compiler will flag up where you are using your old api). I don&#x27;t know clojure well enough, so, what&#x27;s the similar workflow there?
评论 #6959891 未加载
Shamanmuni超过 11 年前
The article starts saying that Scala gives you lots of options while Clojure guides you to a certain style, but the Scala example takes the most complicated solution as if every programmer would solve it that way. He&#x27;s contradicting himself.<p>Scala can solve it in a way quite similar to Clojure. The author is trying to hammer a point about Clojure which doesn&#x27;t emerge from the example, as most Scala programmers can notice.<p>It would have been great if he had listed all the possible solutions and told us &quot;Scala lets you solve it in all these very different ways without the language guiding you, Clojure guides you to the simpler solution&quot;. That&#x27;s a fair point, and one Scala programmers will tend to agree with.
评论 #6959362 未加载
dzderic超过 11 年前
The example cited here is insulting to everyone&#x27;s intelligence:<p><pre><code> The possibility of representing face cards with a name would likely never occur to you, because it would be too complicated to go through the effort of defining the type of a rank to be a &quot;integer or a class comprised of four case classes -- jack,queen,king,ace&quot;. </code></pre> I&#x27;m sure every competent Scala developer will see that the equivalent in Clojure can be done with <i>val King = 13; val Queen = 12; ...</i>, which also means you get ordering for free as you&#x27;re not mixing ints and keywords.<p>I do agree with the author&#x27;s point that Clojure almost forces you to adopt a simpler design, but I feel that long-term maintainability requires a delicate balance of simplicity and structure that can be achieved with Scala, but takes more self-control with Clojure.
评论 #6959223 未加载
wiremine超过 11 年前
Scala feels like the Perl of the modern era: there is more than one way to do it. There is value in that mode of thinking, and Perl is a better language than people give it credit for.<p>However, I think there&#x27;s a reason Python and Ruby have overtaken Perl in the interpreted language space: Python values simpler solutions [1]. Ruby also values a certain type of beauty over Perl.<p>Clojure&#x2F;Scala is a similar dichotomy. Scala has everything you might need, while Clojure is rooted in the spartan power lisp provides.<p>Also, I wonder: if they weren&#x27;t both JVM languages, would we even be having this type of discussion? I mean, we aren&#x27;t comparing Clojure to Cobra or D.<p>[1] See the Zen of Python <a href="http://www.python.org/dev/peps/pep-0020/" rel="nofollow">http:&#x2F;&#x2F;www.python.org&#x2F;dev&#x2F;peps&#x2F;pep-0020&#x2F;</a>
评论 #6959467 未加载
评论 #6960013 未加载
评论 #6959940 未加载
anonymoushn超过 11 年前
<p><pre><code> type Card = (Any, Any) type Deck = Seq[Card] val foo: Deck = Seq((4, &#x27;clubs), (&#x27;king, &#x27;diamonds)) </code></pre> It seems to work over here. I would have to be a bit out of my mind to actually want to write code this way, though.<p>As to the &quot;Lightweight data modeling&quot; pitch, there&#x27;s a pretty large number of other languages that are better suited to this because they have TCO (when run on their main platforms, the analogues of the Sun JVM) and don&#x27;t require you to debug apparently-endless stack traces in a different language when your completely untyped exploration&#x2F;prototype inevitably explodes.
hrjet超过 11 年前
Looks like a slow news day.<p>A dynamically typed language is <i>obviously</i> easier to begin coding in, especially with a trivial example. The problems that statically typed language solve are usually found in larger code bases and in performance critical applications.
评论 #6960440 未加载
评论 #6959954 未加载
dragonwriter超过 11 年前
&gt; On the other hand, in Scala, you&#x27;d be more likely to create a card Class with a rank and suit field.<p>No, if I was trying to do something intended to be generic, I&#x27;d be tempted to start out with this definition of Card:<p><pre><code> trait Card </code></pre> Scala makes it cheap to use descriptive type names while starting out making minimal assumptions. This helps avoid making too many assumptions up front, like the whole model-cards-as-ints one.<p>&gt; For modeling the deck, you probably wouldn&#x27;t say a Deck is-a sequence, because composition is favored over inheritance.<p>&quot;X is favored over Y&quot; does not mean &quot;never use Y&quot;. And, in Scala, &quot;favor composition over inheritance&quot; mostly strongly applies when you are talking about classes, particular classes as the thing being either composed or inherited from.<p>I&#x27;d probably say something like:<p><pre><code> trait Deck[C&lt;:Card] extends Seq[C] { ...whatever special behavior Decks need to support in general... }</code></pre>
lukev超过 11 年前
I find it interesting that there are about 50 comments in this thread discussing the best&#x2F;better ways to model the problem in Scala, and no controversy at all about the Clojure implementation.<p>That&#x27;s a feature of Clojure, IMO.
kailuowang超过 11 年前
I am not sure I would agree that the deck example he gave represents the Scala idiom. I myself would probably start with something like<p>========================<p>object Cards {<p>type Deck = Seq[Card]<p>case class Card(r:Rank, s:Suite)<p>type Rank = Int<p>sealed trait Suite<p>case object Spade extends Suite<p>case object Heart extends Suite<p>case object Diamond extends Suite<p>case object Club extends Suite<p>}<p>==================================<p>Granted, all this code is unnecessary in Clojure but there are two benefits of writing them:<p>1) compilation type check<p>2) for developers who have no context of playing cards, this provides a clearer picture, while in the Clojure code they will have to browse more code to get the full picture of the data domain.
评论 #6960543 未加载
jaxytee超过 11 年前
After modeling Clojure&#x27;s Card Deck as a simple sequence of maps, the author models Scala&#x27;s card deck in an overly complex way using a Deck Class with a nested card class, and each card nesting four distinct case classes to represent suit (Yikes!). The author defends the terrible Scala design by writing:<p>&gt; Sure, you could eschew objects in Scala and mimic Clojure by using generic maps&#x2F;vectors&#x2F;lists&#x2F;sets for all your structured data needs, but that&#x27;s clearly not how Scala is meant to be used.<p>Scala isn&#x27;t &quot;meant to be used&quot; any way. Scala is a lots of things (often times to its detriment) but opinionated is not one. The author even alludes to this early in the post:<p>&gt; Ten years ago, I would have said that my ideal dream language is one that provides the flexibility to program in any style. I want to be able to choose object-oriented or functional, immutable or mutable, high-level abstractions or low-level speed. With respect to this ideal, Scala clearly wins, supporting more programming styles than Clojure.<p>Classic fanboyism, as the author purposely created a shitty Scala example. I would advise that someone investigating functional languages on the JVM take this post with a grain of salt.
评论 #6959967 未加载
edoloughlin超过 11 年前
<i>Well, imagine if you could represent all your data as JSON, rather than a complex hierarchy of objects and methods, and the language was designed around making that kind of data super-easy to work with.</i><p>Then imagine that you could represent your code as JSON and also that a database existed that let you store and build queries on JSON directly (i.e., Datomic).
评论 #6959235 未加载
pron超过 11 年前
I actually think that Clojure&#x27;s relatively unique feature which differentiates it from most languages (other than, perhaps, Erlang and Haskell) is its emphasis on managing state, especially in the face of concurrency.
评论 #6959359 未加载
mcguire超过 11 年前
If object-oriented programmers (here represented by Scala-ites) are excessively fond of modelling the crap out of stuff, to the detriment of the code they&#x27;re trying to write, there is also a problem with the opposite, &quot;lightweight data modelling&quot; approach: a weird fascination with representations of data, instead of the structure of it.<p>Here&#x27;s an example from <i>Land of Lisp</i>:<p><pre><code> (defun limit-tree-depth (tree depth) (list (car tree) (cadr tree) (if (zerop depth) (lazy-nil) (lazy-mapcar (lambda (move) (list (car move) (limit-tree-depth (cadr move) (1- depth)))) (caddr tree))))) </code></pre> and here&#x27;s the version that I re-wrote, using your friend and mine, defstruct:<p><pre><code> (defun limit-tree-depth (tree depth) (labels ((limit-depth-move (move) (let* ((next-tree (limit-tree-depth (get-tree move) (1- depth)))) (if (passing-move-p move) (make-passing-move :tree next-tree) (make-attacking-move :src (attacking-move-src move) :dst (attacking-move-dst move) :tree next-tree))))) (make-tree-node :player (tree-node-player tree) :board (tree-node-board tree) :moves (if (zerop depth) (lazy-nil) (lazy-mapcar #&#x27;limit-depth-move (tree-node-moves tree)))))) </code></pre> I submit that the second may be preferable, even if it is a bit more verbose.
评论 #6963245 未加载
vorg超过 11 年前
&gt; All or nearly all of the functional aspects of Clojure have counterparts in Scala. On top of that, Scala provides [...]<p>Scala doesn&#x27;t provide the syntactic macros, or the same simpler approach to concurrency.
评论 #6959323 未加载
vorg超过 11 年前
There seem to be 4 primary programming paradigms available on the JVM...<p>Clojure - concurrency (immutable by default), macros (lisp-style)<p>Scala - object&#x2F;functional fusion, lazy evaluation<p>Ruby dialect (JRuby or Groovy) - &quot;methodMissing&quot; meta-object protocol<p>Java - low-level OOP (but functional lambdas and lazy streams coming in Java 8)<p>COMING SOON: Javascript (Rhino or Nashorn) - functional with prototype-style OOP
评论 #6959816 未加载
评论 #6961176 未加载
jds375超过 11 年前
So it seems sometimes that being &#x27;forced&#x27; to adhere to lightweight data structures and functional methods makes all the difference. I&#x27;d tend to agree with you, as I have noticed that it is hard to avoid OO and imperative techniques when I have that option.
kvtrew76557超过 11 年前
Perhaps I&#x27;m missing something about Clojure, but it looks completely and utterly foreign. As someone who didn&#x27;t have much trouble learning a &quot;complex&quot; language like Scala I find Clojure really hard to fathom.
评论 #6960970 未加载
评论 #6960473 未加载
评论 #6960347 未加载
laureny超过 11 年前
It seems to me what he calls &quot;lighweight data modeling&quot; is a synonym for &quot;untyped data&quot;. Use ints, strings, arrays and maps to model everything (his JSON example).<p>It&#x27;s great for prototyping but when you start getting big, you really need to tighten these models down to real types.
smrtinsert超过 11 年前
Why vs? What a false choice, I love both of them.
Touche超过 11 年前
There is no language I love more than Clojure but I would never describe it as &quot;lightweight&quot; (as I wait 5-10 seconds for lein repl to load).
mortyseinfeld超过 11 年前
Despite the &quot;kumbaya, we&#x27;re functional brothers...we all win&quot;, I know for fact (very reliable sources) that the Typesafe guys absolutely hate the traction that Clojure is getting, especially that they need to get a ROI on their funding.