The general consensus from what I've read is that to execute a system command in Scala, you should use the Java runtime features. I don't like this, Scala should be more concise than Java. SBT has classes to execute system commands, however, these are generally only available in your build code. To use this code in your program, download these two files: Process.scala and ProcessImpl.scala (available at the Github repo xsbt's util process). Put these files in your src, and then:
Calling !! will block until the command is finished, output errors to stderr, and return the output form the command. If the command returns a non-zero code, and exception is thrown. Calling ! will block, output to stderr and stdout, and return the return code of the command. No exeception is thrown when using !. Look at the code for the ProcessBuilder trait to see other functions that you can call, there are many.
Showing posts with label scala. Show all posts
Showing posts with label scala. Show all posts
Sunday, November 27, 2011
Saturday, November 26, 2011
Using Lift JSON to return a Map from JSON
It's easy to convert a JSON string in to a key/value pair Map with Lift JSON. I found out how to do this from the Stack Overflow question Can I use the Scala lift-json library to parse a JSON into a Map?
First, if you don't already have Lift JSON in your project, you'll need to add it. For SBT projects, add this to your project build file:
Here is the example code for how to get a Map back:
That's all there is to it. If you knew that every value was a particular type, like String, you could specify that instead of Any in the asInstanceOf conversion.
First, if you don't already have Lift JSON in your project, you'll need to add it. For SBT projects, add this to your project build file:
Here is the example code for how to get a Map back:
That's all there is to it. If you knew that every value was a particular type, like String, you could specify that instead of Any in the asInstanceOf conversion.
Friday, November 25, 2011
HTTP authentication with Scala Dispatch
I had some trouble getting basic HTTP authentication to work with the Dispatch library. The documentation and message posts that I've seen say to use the .as(username, password) function on the HTTP request. However, this did not work for me. I had to use the as_! function instead of as. Example:
I believe using as will make a request without authentication, look for a 401 response header, and then re-issue the request with authentication. The Github API, and many others I imagine, do not send a 401 response back when not authenticated.
I believe using as will make a request without authentication, look for a 401 response header, and then re-issue the request with authentication. The Github API, and many others I imagine, do not send a 401 response back when not authenticated.
Labels:
authentication,
dispatch,
http,
scala
Sunday, November 13, 2011
Writing generic functions that take classes as parameters
It is possible to write generic functions that take a class as a parameter, allowing you to dynamically instantiate and/or reference a class within a function, without that function having to know what the class actually is. Scala has always had support for parameterized types. But if you want to do something with the class, like instantiate it or pass it to something else, you have to use the the Manifest feature.
Say you want a function that will return a new instance of the type of class passed in to the function. Here is how you do it:
That's all there is to it! Just specify : Manifest in the definition of the type T, and you can specify it as any class. To access the type, you must pass it as the class to the manifest function. You can do operations on this directly, but if you want to instantiate, call .erasure on it. This will return a scala class. Call newInstance to instantiate. Then call asInstanceOf to convert it in to the exact type you are expecting (T).
This is a really simple example. For a more complex example, let's look at my GithubApi class. I need to write a function that will make an HTTP request to Github's API (which returns a JSON array) for a specific API end point, and convert the response JSON in to a class that I specify when calling the function (which is the expected response from the particular end point). The class will always extend my base class "GithubClass". See my previous blog post Making HTTP Requests and parsing JSON responses in Scala for more info on how to make the HTTP request and parse the response.
That's a lot of code so let me try to break it down. First we define a base class. Then two classes which represent data that comes back from Github, that extend the base class. Then a GithubApi class which will just contain a function to make a request. Let's look at the definition of the function getData:
First we're using the Scala parameterized type here to pass in the type of class that we expect. The T <: GithubClass means that type passed in must extend GithubClass, if we try to send something that does not, it won't compile. The : Manifest means that the type is going to be accessible in the function manifested. path is the path to the API. Finally, we're returning a list of the items of the type that we pass in. Now let's look at the line that actually converts the JSON data in to the type specified:
Here, we're looping through everything returned from Github, and for each item, we're converting the JSON in to the class of the type passed in (extract is a lift JSON function that converts their JSON in to an instance of your class). We can simply refer to the class as T.
Pretty powerful stuff, huh? This combines the best of dynamic languages like Ruby, where you can pass classes around anywhere you want, and static languages like Java where you can enforce types and know what you're passing in and getting back.
Say you want a function that will return a new instance of the type of class passed in to the function. Here is how you do it:
That's all there is to it! Just specify : Manifest in the definition of the type T, and you can specify it as any class. To access the type, you must pass it as the class to the manifest function. You can do operations on this directly, but if you want to instantiate, call .erasure on it. This will return a scala class. Call newInstance to instantiate. Then call asInstanceOf to convert it in to the exact type you are expecting (T).
This is a really simple example. For a more complex example, let's look at my GithubApi class. I need to write a function that will make an HTTP request to Github's API (which returns a JSON array) for a specific API end point, and convert the response JSON in to a class that I specify when calling the function (which is the expected response from the particular end point). The class will always extend my base class "GithubClass". See my previous blog post Making HTTP Requests and parsing JSON responses in Scala for more info on how to make the HTTP request and parse the response.
That's a lot of code so let me try to break it down. First we define a base class. Then two classes which represent data that comes back from Github, that extend the base class. Then a GithubApi class which will just contain a function to make a request. Let's look at the definition of the function getData:
def getData[T <: GithubClass : Manifest](path: String) : List[T] = {
First we're using the Scala parameterized type here to pass in the type of class that we expect. The T <: GithubClass means that type passed in must extend GithubClass, if we try to send something that does not, it won't compile. The : Manifest means that the type is going to be accessible in the function manifested. path is the path to the API. Finally, we're returning a list of the items of the type that we pass in. Now let's look at the line that actually converts the JSON data in to the type specified:
for (jObj <- rspList) yield jObj.extract[T]
Here, we're looping through everything returned from Github, and for each item, we're converting the JSON in to the class of the type passed in (extract is a lift JSON function that converts their JSON in to an instance of your class). We can simply refer to the class as T.
Pretty powerful stuff, huh? This combines the best of dynamic languages like Ruby, where you can pass classes around anywhere you want, and static languages like Java where you can enforce types and know what you're passing in and getting back.
Labels:
generic,
manifest,
parameterized type,
scala
Friday, November 11, 2011
Making HTTP requests and parsing JSON responses in Scala
One of the first things that I've tried to do on my own in Scala (not following a book or online example) is making HTTP requests and parsing the JSON responses. There are powerful libraries written in Scala to do both of these things, Dispatch for HTTP requests and the Lift JSON library.
Using these libraries as my first introduction to Scala proved to be a little more difficult than what I expected. Coming from a Ruby background I expected to be able to make a single call to do an HTTP request, then a call to parse the JSON out in to a hash/map. Not so in Scala. The added complexity can help when you want to do more advanced things, and allows you to give a clear definition to the expected JSON data, but makes it a little more challenging to get going at first.
Getting the libraries in your project
First, you'll need to import the dispatch and lift-json libraries in to your project. For SBT, add the following to your project build class:
Then type reload and update at the sbt prompt.
As of this writing, 0.8.6 is the lastest dispatch. There is a 2.4 for lift-json, but I couldn't get it to work with Scala 2.8.
Making the HTTP request
Next, let's make an actual HTTP request. For this example I'll be talking with the Github API. We'll make a request to get a list of all of my repos. See http://developer.github.com/v3/repos/ for details on this API. Here is the code:
First things first, the import lines will import everything for dispatch and Lift JSON. Next, line 4, we make a dispatch Http object that we will perform operations on. Line 5 is making an object for the specific request. Line 8 is where it gets interesting. With dispatch, when creating and processing requests, you can chain any number of operations together to perform any type of processing that you want. The Periodic Table of Dispatch Operators has most of the possible operators that you can use (although the one we're using is not there).
Confused? Totally lost? So was I when I tried to use Dispatch for the first time. I'm not sure why Dispatch makes the operations so cryptic. The point of having symbols for functions/operations is so that if you're calling the function many times it can save you some typing and brain power when reading. Well, no one is going to use any of these operators all of the time, so why make everything symbols? To make it so that you feel smarter by making the code more cryptic?
Alright, back to my code example. What >:+ does is execute the request the left, and pass the HTTP headers and the request itself in to a function. headers is a Map for all HTTP headers. On line 9 I'm grabbing the headers, if you want to actually process them you can do that in this anonymous function. The return value of this anonymous function will get returned from the call to the http object. On line 10, I'm using the second parameter to the anonymous function, which is the actual processed HTTP request. You can chain together any number of calls here if you wanted to do further processing, since you have full access to the HTTP request. In my case, the only other thing that I want to do is get the response body as a a string. I'm simply calling as_str on the request, which will return a string. So back to line 8, rspStr now contains a string with the response as a string.
Note that if you just want to get the response body and don't care about the headers, you could just write it like:
Processing the JSON data
Now that we have the data, how do we process the JSON? Dispatch has some built in handlers to turn it in to a JSON object, but I couldn't get my project to compile when I included this. Dispatch just uses the Lift JSON library anyway so we might as well use it ourselves.
Lift JSON has some pretty advanced syntax for looking for specific things in the JSON returned. In my case, I want an object that has all of the data from the response, with types so that way other parts of code can use the response. It's pretty easy to do this with Lift JSON. First, we have to define a "case class" that will represent the data. A case class is a class in Scala that can easily be used for pattern matching.
That represents all of the parameters returned from the JSON. If you have a field that may or may not be in the response, specify the type as Option[Type].
Now let's parse the response string as JSON and convert it in to a list of Repo instances.
Line 2 is really important, if you're using the extract method to convert JSON in to a case class you need this or else you'll get an error when compiling saying "could not find implicit value for parameter formats". Line 3 calls the Lift JSON parse function, which will return a JValue. Since the Github response for this particular request is an array of objects, to loop through these we'll need to get a list of these objects. Line 6 does this, rspList is List[JObject]. Finally, on line 7, we're looping through each object (a JObject), and converting it in to an instance of the case class Repo using the extract method. The code after yield gets run for each JObject in rspList. rspRepos now contains a list of Repos for all of my Github code repositories.
So that's it. It's a lot to explain for something seemingly simple, and this took me a while to really get the hang of it. But now that you know how to use Dispatch and Lift JSON you can do some really powerful stuff.
If you want to see this in action, see my GithubApi Scala class:
https://github.com/brentsowers1/GithubCodeFixer/blob/master/src/main/scala/GithubApi.scala
Using these libraries as my first introduction to Scala proved to be a little more difficult than what I expected. Coming from a Ruby background I expected to be able to make a single call to do an HTTP request, then a call to parse the JSON out in to a hash/map. Not so in Scala. The added complexity can help when you want to do more advanced things, and allows you to give a clear definition to the expected JSON data, but makes it a little more challenging to get going at first.
Getting the libraries in your project
First, you'll need to import the dispatch and lift-json libraries in to your project. For SBT, add the following to your project build class:
Then type reload and update at the sbt prompt.
As of this writing, 0.8.6 is the lastest dispatch. There is a 2.4 for lift-json, but I couldn't get it to work with Scala 2.8.
Making the HTTP request
Next, let's make an actual HTTP request. For this example I'll be talking with the Github API. We'll make a request to get a list of all of my repos. See http://developer.github.com/v3/repos/ for details on this API. Here is the code:
First things first, the import lines will import everything for dispatch and Lift JSON. Next, line 4, we make a dispatch Http object that we will perform operations on. Line 5 is making an object for the specific request. Line 8 is where it gets interesting. With dispatch, when creating and processing requests, you can chain any number of operations together to perform any type of processing that you want. The Periodic Table of Dispatch Operators has most of the possible operators that you can use (although the one we're using is not there).
Confused? Totally lost? So was I when I tried to use Dispatch for the first time. I'm not sure why Dispatch makes the operations so cryptic. The point of having symbols for functions/operations is so that if you're calling the function many times it can save you some typing and brain power when reading. Well, no one is going to use any of these operators all of the time, so why make everything symbols? To make it so that you feel smarter by making the code more cryptic?
Alright, back to my code example. What >:+ does is execute the request the left, and pass the HTTP headers and the request itself in to a function. headers is a Map for all HTTP headers. On line 9 I'm grabbing the headers, if you want to actually process them you can do that in this anonymous function. The return value of this anonymous function will get returned from the call to the http object. On line 10, I'm using the second parameter to the anonymous function, which is the actual processed HTTP request. You can chain together any number of calls here if you wanted to do further processing, since you have full access to the HTTP request. In my case, the only other thing that I want to do is get the response body as a a string. I'm simply calling as_str on the request, which will return a string. So back to line 8, rspStr now contains a string with the response as a string.
Note that if you just want to get the response body and don't care about the headers, you could just write it like:
val rspStr = h(req as_str)
Processing the JSON data
Now that we have the data, how do we process the JSON? Dispatch has some built in handlers to turn it in to a JSON object, but I couldn't get my project to compile when I included this. Dispatch just uses the Lift JSON library anyway so we might as well use it ourselves.
Lift JSON has some pretty advanced syntax for looking for specific things in the JSON returned. In my case, I want an object that has all of the data from the response, with types so that way other parts of code can use the response. It's pretty easy to do this with Lift JSON. First, we have to define a "case class" that will represent the data. A case class is a class in Scala that can easily be used for pattern matching.
That represents all of the parameters returned from the JSON. If you have a field that may or may not be in the response, specify the type as Option[Type].
Now let's parse the response string as JSON and convert it in to a list of Repo instances.
Line 2 is really important, if you're using the extract method to convert JSON in to a case class you need this or else you'll get an error when compiling saying "could not find implicit value for parameter formats". Line 3 calls the Lift JSON parse function, which will return a JValue. Since the Github response for this particular request is an array of objects, to loop through these we'll need to get a list of these objects. Line 6 does this, rspList is List[JObject]. Finally, on line 7, we're looping through each object (a JObject), and converting it in to an instance of the case class Repo using the extract method. The code after yield gets run for each JObject in rspList. rspRepos now contains a list of Repos for all of my Github code repositories.
So that's it. It's a lot to explain for something seemingly simple, and this took me a while to really get the hang of it. But now that you know how to use Dispatch and Lift JSON you can do some really powerful stuff.
If you want to see this in action, see my GithubApi Scala class:
https://github.com/brentsowers1/GithubCodeFixer/blob/master/src/main/scala/GithubApi.scala
Sunday, October 23, 2011
Starting a Lift project with SBT and IntelliJ
Getting up and running with Scala and Lift requires a lot of tools, especially if you want to develop from an IDE. Coming from a Ruby on Rails and PHP background, a lot of this was new to me, and the books typically assume you've done a lot of Java development and are used to dealing with build tools, compiling, dependencies, etc.
So this is my guide for how to get started with Scala and Lift development, using the IntelliJ IDEA IDE, based on me spending hours and hours trying to figure it out. I've used Rubymine and PHPStorm which are based on IntelliJ so IntelliJ is definitely my favorite IDE. I believe you can also do Scala development from Eclipse and Netbeans.
I won't use the very latest version of everything, because the very latest of one thing might not be compatible with the other. Also, this assumes you're using Linux, but it will be almost the same on Windows and Mac as most of the action happens in the sbt console. I've gathered much of the info here from the Lift In Action book which I would highly recommend for learning Lift. The setup part of this book wasn't completely comprehensive though and I spent a lot of time with trial and error to get to this point.
Scala
First step is getting Scala set up so you can run Scala from the command line. This is actually optional, but you may occasionally want to manually run Scala code (like irb in Ruby), or compile a stand alone Scala script. We're going to use version 2.8.1, since this is the latest that is compatible with everything else as of this writing. (2.9.1 is the latest as of this writing)
IntelliJ IDEA Project
I didn't forget about using IntelliJ IDEA. Before you open the directory in IntelliJ, you need to create an IntelliJ project file so IntelliJ knows where everything is. This is done from the sbt-idea processor.
So this is my guide for how to get started with Scala and Lift development, using the IntelliJ IDEA IDE, based on me spending hours and hours trying to figure it out. I've used Rubymine and PHPStorm which are based on IntelliJ so IntelliJ is definitely my favorite IDE. I believe you can also do Scala development from Eclipse and Netbeans.
I won't use the very latest version of everything, because the very latest of one thing might not be compatible with the other. Also, this assumes you're using Linux, but it will be almost the same on Windows and Mac as most of the action happens in the sbt console. I've gathered much of the info here from the Lift In Action book which I would highly recommend for learning Lift. The setup part of this book wasn't completely comprehensive though and I spent a lot of time with trial and error to get to this point.
Scala
First step is getting Scala set up so you can run Scala from the command line. This is actually optional, but you may occasionally want to manually run Scala code (like irb in Ruby), or compile a stand alone Scala script. We're going to use version 2.8.1, since this is the latest that is compatible with everything else as of this writing. (2.9.1 is the latest as of this writing)
- Download Scala 2.8.1.
- Extract it to your /opt directory
- "ln -s /opt/scala-2.8.1-final /opt/scala" to create a symlink to your scala folder without having to use the version number.
- "ln -s /opt/scala/bin/scala /usr/local/bin/scala" and "ln -s /opt/scala/bin/scalac /usr/local/bin/scalac" to make links to the scala executable and scala compiler so they'll be in your path.
SBT
Simple Build Tool (SBT) is the command line utility that you'll do pretty much all of the work from, other than editing files. It will compile your code, run your code, load dependencies, load the correct version of Scala for your app, etc. As of this writing, 0.11.0 is the latest. However, after version 0.7.7, sbt had a lot of pretty fundamental changes that I don't like (what happened to it creating the project directory/file structure for you, specifying plugins through the sbt console instead of editing files, etc.) I think version 0.7.7 is easier to use, and it's what the Lift In Action book is written for, so we'll install 0.7.7.
- Download sbt-launch-0.7.7.jar to /usr/local/bin.
- Create a file named sbt in /usr/local/bin with the contents:
java -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=1024m -Xmx512M -Xss4M -jar `dirname $0`/sbt-launch-0.7.7.jar "$@" - "chmod a+x /usr/local/bin/sbt" to allow it to execute
Create The Project
This is a little different that what you may be used to. You'll actually create the project with sbt from the command line, not from your IDE.
- Make a directory for your project and cd in to it
- Run "sbt". It will ask you if you want to create a new project, enter y.
- Enter a name for your project
- Enter an organization.
- Enter a version number for your app
- Enter 2.8.1 for the Scala version
- Use the default 0.7.7 for the sbt version
Lift
You don't need to download and install Lift, this is all done from a tool called Lifty which is a module to sbt. It will give you a "lift" command in sbt that performs lift actions. As of this writing, 1.6.1 is the latest released version of lifty, which only works with sbt 0.7.7. There is a 1.7 beta that claims sbt 0.10 support. We're going to go with 1.6.1.
- From an sbt prompt, enter "*lift is org.lifty lifty 1.6.1". This will install the lifty module globally, to allow you to type lift. (In newer versions of sbt, you can't do this, you have to edit a file and put Scala code in, why did they take out this ability?)
- Assuming you're in the project directory, run "lift create project-blank". This will make your project a Lift project, with the default files.
- Leave the default value for mainpack
- Enter 2.3 for the liftversion (this is important, do not use the default 2.3-RC version, or 2.4 which is not compatible with Scala 2.8.1)
- Enter "reload" at the prompt to reload the project definition
- Enter "update" to compile your blank app
Your app is now compiled and ready to run! You can type jetty-run to start up a web server for your app, then navigate to localhost:8080. Type enter then jetty-stop to stop the server.
IntelliJ IDEA Project
I didn't forget about using IntelliJ IDEA. Before you open the directory in IntelliJ, you need to create an IntelliJ project file so IntelliJ knows where everything is. This is done from the sbt-idea processor.
- From an sbt prompt, type "*sbtIdeaRepo at http://mpeltonen.github.com/maven/" sbt-idea is not in the standard scala-tools.org repo so you'll need to add a reference to it with this command.
- Install it with "*idea is com.github.mpeltonen sbt-idea-processor 0.4.0". This will add "idea" as an option to the sbt prompt.
- Type "update" to update references
- In your project directory, type "idea". This will create the project file for IntelliJ.
IntelliJ IDEA
Now on to the IntelliJ program itself.
- Load IntelliJ IDEA, and before opening the project, go to File, Settings, Plugins.
- In the Available tab, add the Scala and SBT plugins.
- Restart IntelliJ, go to File, Open Project, and find your project. It will take some time to index everything.
- You'll see an error "Cannot load facet Web". Click Details and click Yes to remove it."
- You MAY have to add the lib and lib_managed folders as libraries. I can't explain it, I had to do this on the first project I set up, on the second I didn't. If you do, go to File, Project Structure, Libraries, Add a New Project Library called Libs, Attach Jar Directories, and pick the lib and lib_managed/scala-2.8.1/compile folders. Also for some reason, it will not pick up some of the Lift JAR files that are in lib_managed. I could not get it to recognize mapper, so on this same page I had to click Add Classes and pick the mapper JAR file in lib_managed.
- You'll have to configure the SBT plugin. Go to File, Settings, SBT. Under IDE settings, enter /usr/local/bin/sbt-launch-0.7.7.jar for SBT launcher JAR file
Now that this is configured, you can use the SBT console at the bottom. Just click start, and you'll get a prompt for this project. This is where you'll want to run everything from.
Debugging
If you want to use break points and everything else that comes along with debugging, from IntelliJ:
- From the drop down on the top menu, click Edit Configurations
- Click +, then Remote.
- Give it a name (like jetty debug)
- In the Before Launch section, check Run SBT Action
- Click the ... beside Run SBT Action
- Check Run in current module
- Enter jetty-run for the action
- Click File, Settings, SBT.
- Add the following to the end of the VM Parameters line under IDE settings: "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
You're all set. Just click the Debug button, and you're good to go. SBT will be launched with jetty-run, and you can now debug (note that if you already had an SBT console open, you'll have to kill it).
So, that's all there is to it! :) This is a lot to go through to get going, but now that you've got all of this set up, you should have everything you need to develop with Scala and Lift, and distribute the code when you're done.
So, that's all there is to it! :) This is a lot to go through to get going, but now that you've got all of this set up, you should have everything you need to develop with Scala and Lift, and distribute the code when you're done.
I'm using Scala and Lift now
I've started learning the language Scala and the web framework built with it, Lift. I'll be making some blog posts soon on these.
I'm going to hold off on making any final judgments until I've written some real things in both. But so far I'm really liking Scala and Lift. If you haven't looked in to them, I would recommend you at least give Scala a quick look over. Even if you don't ever intend to use it for your main web app, it can be great for back end processing jobs, as concurrency is built in to the language. And, if like me you work on some projects that can only be distributed to customer's systems that only run the JVM, Scala is built right on top of Java. Sometimes JRuby will allow you to distribute on to the JVM, but you don't always get the newest and best running JRuby.
I'm going to hold off on making any final judgments until I've written some real things in both. But so far I'm really liking Scala and Lift. If you haven't looked in to them, I would recommend you at least give Scala a quick look over. Even if you don't ever intend to use it for your main web app, it can be great for back end processing jobs, as concurrency is built in to the language. And, if like me you work on some projects that can only be distributed to customer's systems that only run the JVM, Scala is built right on top of Java. Sometimes JRuby will allow you to distribute on to the JVM, but you don't always get the newest and best running JRuby.
Learning Scala and Lift and blog background
Several months ago I read the awesome book Seven Programming Languages In Seven Weeks, and knew I wanted to learn some more about Scala. Most of the projects I work on are low volume and wouldn't necessarily benefit a whole lot from using Scala, so I couldn't motivate myself to learn a whole new language that I might not even use. Then I read about the Lift framework, and knew I wanted to learn both and create something real with them, regardless of what the projects I do at work are.
I've read through Programming Scala, another great book published by The Pragmatic Bookshelf, and feel that I can really develop some good Scala applications. I've just now started reading Lift In Action to learn about Lift. Since the community around Lift is still pretty small, and there are a lot of rapidly moving pieces with Lift, I wanted to start blogging about using Scala and Lift. My main goal here will be to post helpful info that will save others some time.
So some background on me. I've been doing software development for over 9 years, with the past 5 years of that being web application development. I've done mostly Ruby on Rails and some PHP for those 5 years. While I do still like Ruby on Rails, I think it's time for me to learn another new language that overcomes some of the down sides of Ruby and Rails. I was an early adopter of Rails (started using it in 2006, at version 1.1), and I loved programming in something new and revolutionary. I have a feeling Scala and Lift will play this role in the next few years. Soon I'm going to build a side project with Scala and Lift, and I'm hoping I can incorporate it in to projects at my job.
I've read through Programming Scala, another great book published by The Pragmatic Bookshelf, and feel that I can really develop some good Scala applications. I've just now started reading Lift In Action to learn about Lift. Since the community around Lift is still pretty small, and there are a lot of rapidly moving pieces with Lift, I wanted to start blogging about using Scala and Lift. My main goal here will be to post helpful info that will save others some time.
So some background on me. I've been doing software development for over 9 years, with the past 5 years of that being web application development. I've done mostly Ruby on Rails and some PHP for those 5 years. While I do still like Ruby on Rails, I think it's time for me to learn another new language that overcomes some of the down sides of Ruby and Rails. I was an early adopter of Rails (started using it in 2006, at version 1.1), and I loved programming in something new and revolutionary. I have a feeling Scala and Lift will play this role in the next few years. Soon I'm going to build a side project with Scala and Lift, and I'm hoping I can incorporate it in to projects at my job.
Subscribe to:
Posts (Atom)