Scala Feels like EJB 2 (blog.joda.org) |
Scala Feels like EJB 2 (blog.joda.org) |
If you want a dynamic language, you have lots of great choices. If you want powerful syntactic abstractions, you have Clojure, Lisp or Racket. You can win big with any of these tools.
But some problems benefit from powerful mathematical abstractions, and that's where Haskell and Scala start to shine. For example, if you need to do Bayesian filtering, you can bury all the math in a monad, and make Bayes' rule as easy as an 'if' statement. (I've got a blog post for the curious: http://www.randomhacks.net/articles/2007/02/22/bayes-rule-an... ) And when your library designs start involving generalizations of linear algebra, even Ruby-lovers may learn to appreciate a strong type system.
But this raises the real question: How useful is Scala if you don't need to do functional programming with a strong type system? Most people don't, at least today, and the jury's still out on whether it will ever be mainstream. Certainly, some smaller companies will use Scala and win big in specialized domains. But if Java hackers want to claim that Scala's an inappropriate tool for their jobs, who am I to argue? I write far more Ruby than Haskell, because I encounter lots of work that's well-suited to Ruby. (Of course, there's also Akka and a lot of other useful Scala features, which may appeal to people who don't need FP.)
So if Scala becomes seriously popular, I'll be delighted. But a large fraction of Scala's complexity is devoted to niche use cases, and that may make some people unhappy if they're merely looking for a "better Java".
Functional programming with a strong type system, IMO, has much wider applicability than just the esoteric mathematical abstractions (e.g. Haskell/scalaz) that you're asserting is a niche for Scala.
I can think of many non-scalaz uses of Scala, but even for non-Scala uses, look at Jane Street's evangelism of OCaml (functional + strong type system) for financial systems.
(Note that, personally, while I like the benefits of FP, I admittedly still think in/like aspects of OO, even if just out of habit, so I find Scala's blend particularly nice.)
I've found over the last few years that my thinking has morphed from primarily OO to primarily functional. It isn't for lack of writing OO code, which I do professionally. I find that my brain loves to think in terms of functional transformations on classes of data types.
Suddenly I find myself noticing when things should be expressed as a monad or monoid. I also find myself thinking in type signatures for dynamic languages and silently cursing the language designer who decided a function can return null without warning. I see patterns in my code and find myself wishing I could overload the semi-colon to implement monadic behavior.
Everything I do with probability ends up looking mathematically dissimilar to probability. Most algorithms go far out of their way to avoid on-the-fly normalization because it's so expensive. An EM update monad is just the State monad.
I love Haskell (never used Scala) but I find the very things you're marketing it with abhorrent to use.
But when you're designing a library, and a variable contains the free module over nullable real numbers, then the type checker is your friend. At least I can't keep that stuff straight without lots of help. And Haskell's ability to do compile-time dispatch on the desired return type of a function makes monads cleaner, too.
If you want to do this in Clojure, see "Typing Haskell in Haskell" http://web.cecs.pdx.edu/~mpj/thih/ , and whip up some macros that do Hindley-Milner type inference with type classes. And if you do, please e-mail me so I can play with it. :-)
A) The language doesn't fall apart as soon as you try something not imagined by the original language creators.
B) Pushing the boundaries actually returns useful results.
C) Java isn't able to solve the given task or at least not productively.
That doesn't make Scala a non-general-purpose language. Probably the majority out there is using Scala as a better Java and is perfectly happy with it.
firstly it is never good when you start out a discussion by saying now I know people will disagree but thats because their bigoted zelots. Its kind of disingenuous to attempt to post a technical dissent filled with personal opinion and preface it with that kind of clause inevitability allowing you to label any dissent as "See those scala zelots are at it again"
That being said this is an article that attempts to raise technical problems with scala but really just list a few of the authors own personal gripes with the language. In order here are his complaints
1. Scala doesn't have a rigid versioned module system 2. The functional way of doing concurrency isn't how I like to do concurrency 3. The scala community isn't helpful enough for me 4. The type system is too powerfull 5. The syntax is too flexable 6. There aren't enough tests in the compiler test suite
Its alot of the same thing I have seen when people try to list "The" problems with the language and not "Their" problems with the language. Technically there is only one argument that could even hold water thats about the module system . Which if he really needs a module system for his work then that is a technical limitation of the language and he might consider using a better tool for his job. The rest of it however is just nonsense and personal opinion pretending to be technical dissent.
The book also weighs in at 883 pages and I was astonished how much of it I needed to read to even get started. Once I did, I very much like what I saw. But I was a big fan of ML back in grad school.
I do share some of the blog author's gripes though. Most of the popular Scala libraries are just a mess of DSL operators that have no real world association. I'm constantly having to look up what an operator means. I still have no clue how to use the Dispatch library, since the concepts it encapsulates are about 400 pages deeper into the book than I'm currently at. This, just to issue an HTTP GET request. I really thought there might be something on the lines of Ruby's rest-client library.
Additionally, my issues with versioning occur at a much simpler level. The release notes of any given Scala release are devoid of anything useful. Usually it's just a list of JIRA issue numbers (not the issue titles). And then there was this whole debacle around 2.9.0.1 and how SBT called the version. That took me 4 hours longer to work than was really necessary.
So, anyway, I do have some Scala projects. Incidentally they're all Java interop because I just can't wrap my head around how to use most of the Scala-specific libraries. But I've found it works really well in those situations. Deep down I really do like the language. The Scala ecosystem leaves a lot to be desired, but fortunately I can pull in stuff from elsewhere on the JVM.
- Compatible with JVM
- Strong type system
- Linear Typing
- Substructal Types
- Local Type inference
- Concurrency constructs built in as actors (Akka)- Integration of OO and functional paradigms
- Supports Higher Order Programming
- defn-site Variance based Parametric Polymorphism
- Mixin Class Composition for finer grain reuse
- Traits provide stackable behaviors (aspect-oriented style)
- Embedded Polymorphic Domain Specific Language (DSL) using dependent path types
Every language design is a trade off, but Scala is more expressive and concise than Java. Sometimes that may look to you as code which is unreadable. Other languages like clojure make some other trade offs. But Scala tries to bring some of the benefits of functional programming (in say Haskell) to Java.
Will I still understand my own code in 9 months time?
I think that their is more to being a good language than a list of features.
However, the rest of us lesser mortals use Scala very differently, and we far outnumber these people. If you pay attention to Martin Odersky, the creator of the language, you'll notice that he is more interested in serving our needs than those of the Haskellites. He's outright refused to make IO monads a core part of the language, for instance, even though they have pushed for it. He's also said that scalaz is on another planet entirely, and he's asked publicly that people stop using symbolic method names in their libraries unless they have external meaning beyond the library. This guy gets it. He really has created a language that is powerful, but also practical, an excellent language for writing code that is readable, maintainable, efficient, and concise.
The author of this article admits that Scala doesn't feel right to him. He then proceeds to try to justify that feeling in his mind with some very weak arguments. For instance, his module argument oh so coincidentally happens to play into fantom's strengths alone, as No other JVM language is trying to tackle this problem right now. He is right about the lack of tests and binary incompatibility, but these are known issues that already have been addressed to some extent and are continuing to be addressed. They are not core issues with the language itself.
Scala is lightyears ahead of Fantom and Fantom will probably never catch up. If Fantom can't win on technical merit, then apparently the next best strategy involves negative blogging!
Sure the type system is complicated, but I don't really have to understand all its nuances in order to get my program to compile and work. When you use Scala, after a short while you just develop an intuition for it.
The comparison to EJB 2 is a bit nutty, if you ask me, since writing code in Scala tends to be the antithesis of all the terrible Java monster enterprise library crap. The libraries that people use in Scala tend to be much simpler and more straight-forward.
I do agree that there's a contingent of the Scala community who seem to want to rub their fluency with category theory in your face. This is hardly representative of the entire community, however, and I'm sure they must exist in the communities for almost every functional programming language these days. The solution for this is for people to come up with more intuitive explanations for the powerful tools that category-theory inspired abstractions provide. I know that this can be done, and it will be done, when functional programming become mainstream enough that it attracts better writers.
(I, myself, have been thinking of writing up a little essay called "The Mapcat is the state monad of Massachusetts" to try to explain monads in a better way than comparing them to space suits, or whatever. Okay, okay... mapcat isn't a state monad, but I think the title's funny anyway.)
This is key. People sometimes look at the type signature of the map method (as above) and freak out. It's good to try and understand everything, mind you, and eventually you probably will. The key here is that the crazy signature of the map method simply means the map method will do what you expect. That's it! “But I would write X to do it in my language” is irrelevant, because you don't write the map method. It's provided. There's a paper that describes why the signature is how it is and everything, but you don't care, because it's complicated so that when you're actually using it, it just works.
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
All this complexity to allow for automatic conversions (the following will return a Set[String]) ...
BitSet(1, 2, 3).map { _.toString + "!" }
In a dynamic language, the signature of map is simply this: (a → b) → [a] → [b]
The big difference is that the language doesn't care about types "a" and "b" until runtime. You're the one that cares about it, only on a need-to-know basis. Hence the implicit conversions become explicit (although conversions are less necessary) and code correctness is guarded by unit tests, which you need with Scala anyway. Also, the implementation of "map" in a dynamic language is something that a junior developer can come up with.
So the biggest problems I have with Scala:
1) it is not readable
2) it separates developers in two camps:
library designers and users
3) it does not provide clear benefits
over dynamic languages (Haskell does)If Scala only did what ML and Haskell do, the type signatures would be exactly that.
We have been using Scala for 4 months now and have the first cut of our product released:
The Scala community have been great - we have had insightful answers on the Lift, Akka, Dispatch and Scala users list and on stack exchange.
We have used parallel collections and Akka actors to get good scalability without the usual pain. We do have some mutable data structures where it makes sense - we appreciate the flexibility to do that. The distinction between mutable and immutable data structures is pretty easy to read in the code.
Our code base is very concise, and i think readable for the breath of functionality we have implemented. We have not used type level programming, simple Scala constructs like pattern matching, collections and closures make a huge difference. You can write obtuse code in Scala - we choose not to.
In short we see Scala as a competitive advantage going forward.
As Rich Hickey pointed out recently, "I can't read German; does that mean it's unreadable?"
You don't need to know Python, to understand it on the level of pseudo-code. You don't need to know Clojure to understand it on the level of S-expressions, etc.
- http://en.wikipedia.org/wiki/Commitment_bias
- http://en.wikipedia.org/wiki/Endowment_effect
- http://en.wikipedia.org/wiki/Sunk_costs
- http://en.wikipedia.org/wiki/Herd_behavior
[edit: also, you're inferring the experience of people from the complaints that they make. that means that you are automatically dismissing anyone who makes certain kinds of complaints simply because you know that some people who make those complaints have little experience of scala. so, for a very simple example, you might find that only people with a very high tolerance for type system induced pain can tolerate scala - then you would be dismissing the majority of people, presumably with valid criticisms of scala, just because they are not part of your (self-selected, exceptional - and not necessarily in a good way) clique.]
The thing is that people knowing the language can easily tell apart people who never seriously tried using the language from those who did, because the complains of the first group are so much different from the other group.
Yeah right.
Might I suggest you read more about
- https://en.wikipedia.org/wiki/Cherry_picking_(fallacy)
- https://en.wikipedia.org/wiki/Wikipedia:Neutral_point_of_vie...
Rather pointing out that humanity is flawed. Why don't you try to practice living by virtue and show others the right way ?
It's more honorable than finger pointing from a high horse.
Scala is clearly an improvement over Java (although I wish they'd kept a C-style for loop). I happen to slightly prefer it to Clojure (which is also better than Java for my purposes).
In the non-Java JVM ecosystem, there are always these angry bucket-of-crabs posts from enthusiasts. Ignore them.
If Java is CVS, then Scala is Subversion and Clojure is git.
Scala feels very much like "Java done right". Scala solves a lot of problems with Java and is better in every respect. In the same way, Subversion solved a lot of problems with CVS and is very much "CVS done right".
But the opportunity that was missed was that, just at the Subversion developers never asked themselves "Is centralized version control the right way to do things?", I feel that the Scala developers equally were so focused on fixing the myriad of problems with Java, they never took the step back and asked themselves "Is imperative/mutable state/exposing-Java's-warts-for-compatibility the right way to do things?" Of course, they've built a much better Java, but it feels that they've been so focused on the trees that they've not seen the wood [1].
[1] For non-native English speakers the idiom is http://idioms.thefreedictionary.com/cant+see+the+wood+for+th...
val myList = "Jim" :: "Bob" :: Nil myList(println)
what's hard about that?
Here are my thoughts on it. - I get val myList is some sort of list... - Seems to be a list of Strings. But what is ::? - Nil means list is nullable. Wait is one of the parts of list 'myList(println)' (looks a bit like Smalltalk)? - Why is println the argument and not the method? Is that syntax correct?!
Compare same thing in Fantom. Note ; is only used as a separator and is equal in all respects to '\n'.
myList := ["Jim", "Bob", null]; echo(myList) val nn = List("Jim","Bob")
This creates the same list that the example using :: did. It doesn't need to be explicitly terminated with Nil.; println(myList)
i.e. reorder those and add a semicolon or put it on the next line
and I agree with pivo that "Jim" :: "Bob" :: Nil should be List("Jim", "Bob"). I'm not sure if these are the same as _Y_'s Fantom code, but both of these print out "List(Jim, Bob)" in Scala.
As far as I could tell, they were a classic example of the architecture astronaut's tendency to inflict blue-sky designs on others before actually using them in the real world. They sounded great in the marketing brochures, but were hideous in practice, both for development and run-time use.
The EJB3 transition he mentions came about because EJB as a product was getting its ass kicked by Hibernate and related open-source, field-tested software. Eventually they just threw out EJB2 and said, "Hey, EJB3 is a bold, innovative approach that just happens to look exactly like Hibernate."
The biggest problem for me was readabilty. Scala is the first language that i've learned where at first i couldn't just read code and immediately guess what it does.
I think the prime reason for this is that scala permits operator overloading; more than that, in fact, almost every character can be an identifier. This results in often very cryptic code and libraries, because you can't guess what that function does without reading its definition. quick, what's the difference between +++ and ::: ? what's /: and /:\ ? You can't even google it!
The other big problem for me was the type system. At first it sounded really great, and in fact the amount of compile-time code verification that you can achieve is indeed impressive. But in practice, i found myself fighting with the type system a lot, for example when trying to reuse a function with generic type restrictions that I had't written: some time these can get very long and your only choice is to copy-paste them from the original definition.
Also, how do you test that your type constraints are correct? you can't, by definition, write compilable code that would invalidate them.
Finally, it turns out that a lot of the bad stuff that's in java ends up in scala also, because of runtime compatibility concerns. in particular, scala's generics are an extension of java's. so, for example, almost all generic type information is lost at runtime, except for some extra metadata that scala stores in the object. this results in pretty ugly code when you have a dynamic object and you need to use it with a generic method.
I've been toying with the idea of trying scala for a serious project for a few months, and this part scares me. It's so obviously a bad idea it makes me wonder what other dumb things are in there.
It is also why there are currently plans to integrate Akka actors into the language itself, replacing the builtins.
He does acknowledge that "It could become EJB3" which is a far sight better. But the tone of the rest of his post genuinely seems in conflict with this sentiment.
Another big piece of Scala which makes it a tremendous win over using say, Erlang, Haskell or F#, is that it integrates well with existing Java code. Many shop have been able to do new development in Scala while keeping and leveraging their existing legacy Java codebase. Something that wouldn't be properly available from these other Non-JVM languages.
Clojure of course is JVM based as well; however I'm not as familiar with it and I'll admit I don't know how well it does or does not work with existing Java Code. I do know that a few MongoDB + Clojure driver authors have had issues w/ certain aspects of our Java driver in wrapping it which seemed rather trivial. Not an indictment of Clojure, just the only view of Java compatability I've seen which anecdotally leads me to believe Scala has stronger integration.
Finally, I can't agree enough on the need for modules. It really is a major pain point... but I'm not sure it's one that we can easily fix at this point. I'd still love to see us (The Scala Community) try, however.
val client = new HttpClientXLightWeb
client.host("somesite.com").get[ByteChunk]("/some/url")
That, plus some imports, is all you needIt's mostly an absurd comparison (equivalent to Fibonacci or something), and a tangent besides, but in Clojure:
(slurp "http://somesite.com/some/url")
That gives me the response as a string. If I want a binary stream: (clojure.java.io/input-stream "http://somesite.com/some/url")
The same functions work for URLs, URIs, Files, and strings that describe them.That being said, programmers can over-engineer things in any language; it's just that in Java, over-engineered things are "incomprehensible and huge" while in Scala over-engineering things are usually "incomprehensible and small".
Have any good recommendations for JSON parsers? This was another case where I found the common libraries to be rather obtuse.
val source = scala.io.Source.fromURL("http://news.ycombinator.com/item?id=3264849")Thats a loaded question. I don't know about you but I have met alot of People who write VBScript in excel spreadsheets that call themselfes programmers. To say the language is bad because programmers of all abailities can't understand and use it will make all languages even the simplisest ones fail that test.
You should be asking can programmers that I will be asked to work with understand it and use it, however your answer to that question I think will say more about the programmers you hire / work with then it will about scala.
Although,I agree the code may not be easy to understand for everyone in the beginning but with effort and training I believe every programmer can learn enough of it to be more productive.
I am working with two guys right now who have less than 8 months of programming experience.
They are not having a problem with scala. They can do useful work in it.
What they have a problem with is all the other stuff that you just have to learn about building systems.
I suspect you are thinking of structural subtyping, which is a completely different concept.
Nevertheless I find this statement:
> Scala is lightyears ahead of Fantom and Fantom will probably never catch up. If Fantom can't win on technical merit, then apparently the next best strategy involves negative blogging!
Baseless at best. In what aspect is Scala lightyears ahead?
Also what are you implying by saying 'if it can't win on technical merit then best strategy involves negative blogging!'
First Stephen is just one guy. Second I think Stephen just likes Fantom for the same reasons he dislikes Scala and wanted to blog about it.
The authors and the community have overall been quite ambivalent to Scala. As witnessed by this blog from one of Fantom's authors: http://fantom.org/sidewalk/topic/675
This isn't to say scala couldn't adopt a better system, but I don't think the community has an incentive because scala's main appeal is that it has a steep learning curve, but after you get over the hump you can do everything you want and more. I just think that high barrier to entry, as indicated by the post, may not be worth the benefits.
Part of me thinks you're conflating two separate things: build systems and package repository systems. Even people who hate Maven's build system (myself included) tend to agree that Maven's package management system is really good, and as you like clojure-leiningen, you must agree in some sense.
libraryDependencies += "org.scala-tools" %% "scala-stm" % "0.3"
Although this may not be clear since sbt presents 2 configuration methods, a simple one (as seen above) and a complex one.i don't understand your anger, apart from the fact that you don't like to be wrong.
I am disappointed with Scala and having lived through EJB 1, EJB 2 and then onto Spring and EJB 3, I agree with Steve it makes me feel exactly the same as I felt about EJB 1 and EJB 2 - that is I am being sold overcomplicated technology as a panacea. I want a powerful language with a simple syntax, for example Lisp, ML or Haskell, not a powerful language with a complicated syntax like C++. Does Scala really want to be known as Java++?
I think the criticism of implicits is valid and should be addressed by the scala community, it is a frequent occurrence for me to be left scratching my head when reading code because something is bringing in an implicit declaration unbeknownst to me.
Also one complaint not made by Steve is compile times, reasonable in SBT, unreasonable using the typical build tool used in legacy Java projects.
However, if you are only using objects, calling methods, or even implementing interfaces, interoperation for Clojure is quite nice.
This is just how it seams to me from afar. I don't know if that is right.
https://github.com/lift/lift/tree/master/framework/lift-base...
Here's a summary:
The JSON AST is pretty straightforward. The JSON DSL works like this:
- A tuple ("key", value) constructs a key/value pair
- ~ joins them together to construct an object
E.g. ("foo", 1) ~ ("bar", "Hi") = {"foo": 1, "bar": "Hi"}
I never actually invoke the parser myself. BlueEyes does it if you change the ByteChunk is my example above to JValue.
Drop me an email (noel at untyped dot com) or tweet (@noelwelsh) or IM or Skype or whatever if you want to discuss more.
Alternatively, I've never used Coda Hale's Jerkson package, but I expect it is of high quality.
Does any of raw string <-> JSON AST, or maps/lists <-> JSON (...IIRC), or case objects <-> JSON (what I'm using it for, pseudo ORM).
It means construct a new list.
A cons A (or A :: B) means create a new list with A before B, where B can be a list item or a list itself and A is a list item.
The :: operator is right associative so "Jim" :: "Bob" :: Nil actually works like ("Jim" :: ("Bob" :: Nil) ) (Actually all operators that end in : are right associative in Scala.)
For more see: http://en.wikipedia.org/wiki/Cons
BlueEyes is a framework for writing high performance web services. For it's use cases you care whether you're getting or putting. Thus it is explicit. Similarly, you care about performance, and so don't want to parse strings if you can help it -- thus you set the host once rather than parsing a URL.
For a pure ease-of-use library Dispatch is probably the best, if you can figure out the syntax (see earlier discussion). In Dispatch you can write something like
url("http://somesite.com/some/url") >>> System.out
I forget how you read into a string. Probably change >>> to >>@!#$$T%^@#$% or similar.Of course, more involved interactions require an API with more knobs. Clojure has a number of options, including touching the JDK's HTTP client API, or using a wrapper around something more grounded like clj-http[1] / Apache HTTPComponents.
If you name your method addAll or ++ is pretty much the same. The same rules apply to both. Both can be called the same way:
coll1.addAll(coll2) coll1.++(coll2)
coll1 addAll coll2 coll1 ++ coll2For instance, say you have a String ... well, a String containing what? A name? A regular expression? A number waiting to be converted to floating point? A bank account number? A phone number? An email?
I don't see compile-time type-checking in Scala as something useful, as most often than not it stands in my way. It does help to alleviate some bugs related to incorrect usage of types, but on the other hand you need tests with good code coverage anyway.
http://www.chuusai.com/2011/06/09/scala-union-types-curry-howard/
if you don't want to pay an abstraction tax.I also think many people do not understand the benefits of type abstraction, perhaps because many languages do not even offer it without requiring boxing. Even if your RegEx type is a String, not revealing that to client code is wise engineering.
How about if you want to do stuff only with Employees with a salary greater than X? Consider this case ...
a_employees = employees.filter{|x| x.salary > A}
b_employees = employees.filter{|x| x.salary > B}
# where A > X, B > X
# so both should work with:
def do_stuff(employees) where employees.salary > X
...
In other words, creating new subclasses is a poor substitute for code contracts, especially since many contracts could be checked at compile time.A Typesystem in this still combind with some tools to check this befor you run the programm should provide almost everything you get from Haskell or Scala.
This kind of approach does yield the additional benefits:
1. Much easier to change
2. You can add another static analysing system ontop of it
3. Less restrictive
It is not about what can be expressed, but about how you express things. You do not need function literals in Scala, but it is sure is more concise and cleaner than anonymous classes in Java. You do not need traits in Scala, but it avoids code duplication or the overhead of wrapper classes or proxies in Java. You do not need case classes and algebraic pattern matching in Scala, but it is far more concise and less error prone than having to write the obscene amounts of boilerplate you would write in Java.
And so on.
val time: Time[Int] = 15 s
val length: Length[Int] = 450 m
val speed: Speed[Int] = time / length
The type annotations are of course completely optional.The interesting thing is that while the implementation is quite complex, the actual user has a very simple interface to develop against.
So while you can write complex code in Scala, Scala allows you to keep the complexity in the library-side, while it would bleed into the use-site in Java (use-site generics, anyone?).
Java can't do that. In fact, they already failed twice with it.
If you don't represent these as different data types it's very easy to accidentally lose track of if you sanitized a string or not. Did you sanitize it before you placed it in your model, or do you need to sanitize it before to display it? Did we unsanitize it when we pulled it from the DB? Should we be displaying it unsanitized in the HTML?
If you encode these differences in opaque types it suddenly becomes impossible to make a mistake. It suddenly becomes very easy to reason about a program. Based on the type you can immediately know what type of string you are dealing with and not have to every ask yourself if it has been sanitized yet.
For me, that reduces the complexity of the application and makes reasoning about the program easier. Wise application of types to semantic differences in data can really make a program easier to build.
You must escape all user input you send to the database, and this is normally done by your database driver by using parametrized queries (be they prepared or not). And when the data is retrieved from the database you generally do not have to unescape anything, especially not since the returned data is not SQL strings but in whatever binary protocol is used and is unescaped (if necessary) by your driver.
So what your code should look like is something like:
db.execute("INSERT INTO foo (a, b) VALUES ($1, $2)", a, b)
So for the database you just have two types. Queries and data. Data should always be treated as unsafe while queries is the special class that could help out if you do a lot of manual query building.For this reason any user input needs to be escaped whenever it is rendered in HTML as well. If you got it from the DB it should be safe, but if you got it from the url parameters it isn't.
Haskell is perfectly able to do that as well if desired. `[]` is a monadic type.
Functor f => (a -> b) -> f a -> f b
Defines map for any type that implements the type class functor. Lots of types will implement functor and it is easy to implement it yourself.
For instance, the Ord typeclass extends the Eq typeclass, so any instance of Ord can be used as an instance of Eq. But there is no way to cast an instance of Eq to an instance of Ord.
fmap :: Functor f => (a -> b) -> f a -> f b
BitSet(1, 2, 3).map { _.toString + "!" } // returns Set[String]
The Scala code here starts with one Functor (BitSet) and returns a different Functor (Set), depending on the type of the function (in this case, Int => String). If the function had type (Int => Int), it would still return a BitSet.The signature for fmap does not encode this flexibility.
There are probably map-methods elsewhere, but let's take the map defined on TraversableLike[0]. TraversableLike is a base trait for all kinds of Scala collections (let's just pretend trait is like an interface for now, look it up if you're interested in the details).
TraversableLike has two definitions of map in 2.9.1:
def map [B] (f: (A) ⇒ B): Traversable[B]
def map [B, That] (f: (A) ⇒ B)(implicit bf: CanBuildFrom[Repr, B, That]): That
The first one isn't so bad, is it? The first one takes a function converting objects of A to objects of B, and returns something that is traversable of B (i.e. perhaps a List[B] or Set[B]).The second one can return anything you want, as long as you have a function that describes how the objects can be converted. That is what the implicit is for. For instance, if you map a collection over a function that returns a list of integers, but you actually wanted a set of strings - you can define a function that converts your List[Int] to Set[String]. I recently found a description of canBuildFrom on Stack Overflow that explains this in a bit more detail[1].
As a Scala beginner I find that I often can't expect to understand everything at once - a lot of times it's like other languages, but when it's not I usually can't just guess what it does, but actually have to take time to learn it. I don't think this is a bad thing.
[0]: http://www.scala-lang.org/api/current/index.html#scala.colle...
[1]: http://stackoverflow.com/questions/1721356/scala-2-8-canbuil...
it did not take me long to actually understand
the type signature here
Bullshit. You just followed somebody else's public explanation. Not a problem per se, but this doesn't strike me as beginner friendly ... Dr. Brian Beckman also has a great description of monads on Channel9 that doesn't involve category theory. Does that mean that monad comprehensions are also beginner friendly? if you map a collection over a function
that returns a list of integers, but you
actually wanted a set of strings
Here's some Ruby code for you: [1,2,3].map{|x| x * 2}.map{|x| x.to_s}.to_set
Ironically I find this code written in a dynamic language to be much more readable. Also, give me first-class functions and recursion in a dynamic language and I can implement all of the above by my own (lists, sets and map).See https://apocalisp.wordpress.com/2010/06/16/type-level-progra... for one take on this.
Unfortunately, I don't think many Scala users were around at that time or in that community, so lessons of the past might be learned the hard way again.
There are many encouraging signs too, though, toward better and simpler practices. We'll see which way things go.
func bar() [10]foo
with
var a [8]foo = bar
giving an error like
cannot use bar() (type [10]foo) as type [8]foo in assignment
Is it necessary to use Peano arithmetic to specify a simple type in a general purpose programming language?
But if you want you can also encode the sizes in binary or decimal numbers: http://apocalisp.wordpress.com/2010/06/24/type-level-program... http://www.ict.kth.se/forsyde/files/tutorial/apas03.html
Nah, typeclasses are nominative typing but added post-facto (you can define a typeclass instance for a third party's type). Typeclasses are similar to Scala's traits I think (I don't know if you can add traits to a library's types though).
<li class="<%= user_type %>"><%= username %></li>
Where username and user_type are variables containing data fetched from the database. This template is then compiled to something like the blow. Strings literals of the HTML-safe type start with s", and concatetnation to the output buffer is <<. out << s"<li class=\"" << user_type << s"\">" << username << s"</li>"
So to implement your own templating language and and template helper functions this is a useful concept. But query building should be in the database layer and HTML building in the presentation layer. People using the database should not have to know of or care about that the data might at some point be displayed in a HTML page.Your example is similar to the approach that Yesod, a Haskell web-framework, takes. The templating language, Hamlet, will accept many types, such as Text or String, but ultimately everything gets translated into RepHTML before being rendered to a real HTML string that is sent to the client. Whenever you give the template a value it automatically runs the appropriate conversion function based on type to generate something safe for display on the page.
The only way to get from a String to RepHTML is either to use the proper escaping function (usually done automatically) or use a special function to do an unsafe conversion, forcing you to explicitly state that a conversion is safe.
The type system is one of the tools used to guarantee that these things get sanitized. You can generate RepHTML in other places, such as through a widget, or other helper functions, and it knows at that point that you properly escaped it. Without the type system you could run into issues when a function generates HTML (sanitized) and then the final template re-sanitizes it. It would be very awkward to do things like layout templates if things are getting sanitized many times.
If you're referring to the stack overflow answer, then no. I understood the signature by learning Scala (by reading a book). Is that cheating?
> Does that mean that monad comprehensions are also beginner friendly?
No, not necessarily. Do you have to understand what that even means to be able to use Scala?
> Here's some Ruby code for you
You just tried very hard to not understand the problem at hand, right?
Because the equivalent Scala code looks like this:
Array(1,2,3).map(_*2).map(_.toString).toSet
> I can implement all of the above by my ownSure, if you OK with your code running magnitudes slower than the built-in stuff.
That's probably the main difference between general purpose languages and scripting languages today: General-purpose languages allow you to implement the appropriate data structures yourself, while scripting languages force you to use the built-in stuff.
Sure, if you OK with your code running magnitudes
slower than the built-in stuff
...
scripting languages force you to use the built-in stuff
These 2 sentences don't compile.You should also realize that the speed of the JVM has nothing to do with the static-ness of the language. The bytecode is in fact dynamic ... the only instances where certain assumptions where made based on Java (the language) being:
1) classes are immutable and can't be garbage collected unless you destroy the corresponding class loader
2) the method dispatching done cannot be overridden (so when calling a method on an implicit object, you also have to specify the interface where that method is defined) ... but this has nothing to do with the inner-workings of the JVM and is being addressed with the work done on InvokeDynamic
Really, if you're worrying about "scripting" specific behavior sneaking in on you, stealing away precious CPU cycles or RAM bytes, then you should stay away from the JVM.
You still fail to understand that the `map` (and other methods) are far more flexible in Scala, making them play well with sub-typing and inheritance (and in fact with stuff like `String` and arrays which don't implement any collection methods at all).
With your examlpe above, what result collection type would you get when you map with `Int -> String` over a `BitSet` or with `Char -> Int` over a `String`?
> You should also realize that the speed of the JVM has nothing to do with the static-ness of the language.
You have obviously never seen the mess JRuby and Clojure employ to run on the JVM.
http://weblog.rubyonrails.org/
I'm not that familiar with lift and Yesod, but it seems like they're both able to use compile-time checks as additional layers of protection.
The example above was made by me, on purpose to explain the difference, which I did.
On the JVM - I've implemented dozens of parsers and simple compilers, I did a lot of bytecode manipulation. I know my bytecodes, I know very well the challenges involved.
Your oppinion is based on gospel and the authors of Clojure or JRuby dissagree with you ;)