tag:blogger.com,1999:blog-27807296808340998002024-03-08T03:54:41.138-05:00Clojure YapFull time Clojure/CLJS dev, remote worker, and wannabe cellist.Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-2780729680834099800.post-87805499455442160902015-03-21T14:13:00.002-04:002015-03-21T14:13:56.466-04:00Book Review: Clojure Web Development Essentials by Ryan BaldwinA few weeks ago, I got an email from Gavin Cardoza at Packt Publishing offering me a free e-book in exchange for writing a review of Packt's recently-published <i><a href="http://bit.ly/1KhhpxT" rel="nofollow" target="_blank">Clojure Web Development Essentials</a></i>, by Ryan Baldwin. I think I'll turn down the offer of a free e-book, but I'm happy to write a review because I think Baldwin has done an excellent job on the book. (Disclaimer: I did get a review copy of the book at no charge).<br />
<br />
Rather than trying to survey all the tools and libraries available to the Clojure web developer, the author has made the very sensible decision to zero in on Luminus, a mature and well-crafted base project that provides you with the fully-functioning core of a web application, without locking you into a rigid framework. Starting from the Luminus defaults, Baldwin then walks you step by step through the process of configuring the server, configuring the logs (including the tricky bits!), handling forms, persisting data to a SQL database, handling logins, security, and sessions, and finally deploying to production. At each step, you have a fully operational (though incomplete) web application to play with, so the feedback is immediate and satisfying.<br />
<br />
In keeping with the <i>Essentials</i> theme, the author sticks to the basics, and resists the temptation to drag in all the interesting related topics that so often muddy and confuse introductory tutorials. Anywhere Luminus offers the developer a wide range of choices, Baldwin picks a good one and runs with it, without falling down the rabbit hole of trying to consider the strengths and weaknesses of each option. This makes the book much easier to follow, retain, and apply, and keeps it from getting boring. Those other choices are out there, and you can learn them later if you're interested, but when you do, you'll already have the basic essentials down, and will be much better equipped to relate new information to what you already know.<br />
<br />
As a web developer who uses exclusively MySQL (and/or MariaDB) in my day job, I was interested to see that Baldwin chose to focus on PostgreSQL as the database for this book. That's a good choice for anyone interested in deploying to Heroku or a similar platform, where Postgres services are easier to find than MySQL services, but it might surprise you if you're coming to this book from other web development environments like me. If you haven't played with Postgres before, this book might whet your appetite for more.<br />
<br />
If I had to criticize this book for anything, it would be regarding two points. First of all, this book is written from the point of view of a developer working either in OS X or Linux, not Windows. That's understandable, since Clojure development involves a certain amount of command-line work, and Windows brings in a bit more complexity when it comes to getting everything up and running. The omission does make it easier for the book to stay focused on the <i>Essentials</i> of Clojure web development, but might prove frustrating to Windows-based developers trying to get their feet wet in Clojure for the first time.<br />
<br />
My other complaint is that the book does not spend a lot of time on the topic of web security. This, again, is probably a tactical decision in the interests of keeping to the <i>Essentials</i>, but being the naturally paranoid person that I am, I wish the book had devoted more discussion to the topic. It does at least walk through the process of using bcrypt to secure passwords, instead of making the mistake of storing them in a decryptable form, so that's a big point in its favor. But an appendix, or at least a link or two, would not have been amiss.<br />
<br />
Other than those two complaints, I was very impressed by this book. The writing style is lively and interesting, yet clear and to the point. The examples are easy to follow and do a good job of conveying the technology they are trying to explain. And I <i>love</i> his decision to implement his database interactions using YeSQL rather than a more complicated ORM or ORM-ish system. As someone who has to wrestle with ORM syntax every day (in PHP, no less), the simplicity of straight SQL-as-a-function is something I drool over.<br />
<br />
I've got a number of Packt books and I keep going back because they're generally high quality and their e-book format is just right for the Kindle app on my iPad, but I have to say that <i>Clojure Web Development Essentials</i> looks like one of their best so far. Kudos to Ryan Baldwin on a great job, and I hope he decides to do a follow-up book on securing Clojure web applications. (Hint, hint.)Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com0tag:blogger.com,1999:blog-2780729680834099800.post-24049301361452120252013-10-20T13:07:00.002-04:002013-10-20T13:13:10.005-04:00Test-Assisted DesignI'm re-thinking my opinions about unit tests and test-driven design. On the one hand, part of me immediately liked the idea of TDD as soon as I heard it: by writing out your tests first, you have a clear, unambiguous spec for what you're supposed to build. It's clear, because it has to be a test that the machine can run, and it's unambiguous because it's a test. It either passes or it doesn't.<br>
<br>
On the other hand, I've been having second thoughts about unit tests ever since I saw Rich Hickey's talk on <a href="https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CC4QFjAA&url=http%3A%2F%2Fwww.infoq.com%2Fpresentations%2FSimple-Made-Easy&ei=kAVkUouHAsblyQGC3YGICg&usg=AFQjCNGTrfZhyYHCy4apWbZNkfTRI-voyw&sig2=1iyHRXd_y7Tbz-b5iJn3PA&bvm=bv.54934254,d.aWc" target="_blank">Simple Made Easy</a>, the Magna Carta of functional programmers. Tests are good, but-- Tests are necessary, but--<br>
<br>
The thing is, unit tests could be thought of as a kind of code smell, or a kind of technical debt. You're writing tests because <i>you don't know what your code is going to do</i>. And maybe that's unavoidable. Maybe programming is just too complicated for us to write code that always does exactly what we expect it to do. But still, a code smell, a sign of an undesirable circumstance that we should be trying to avoid or reduce.<br>
<br>
<a href="https://clojure-yap.blogspot.com/2013/10/test-assisted-design.html#more">Read more »</a>Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com2tag:blogger.com,1999:blog-2780729680834099800.post-76204034146229404982013-07-29T06:09:00.001-04:002013-07-29T06:09:50.216-04:00Nil is not enoughHere's the context: I'm separating out all my data-store-related functions into their own namespace. Specifically, I'm working on my User model. I want to write a function that creates a new user in my data store, but only if there's not already a user with the same username. No problem, right? If the user already exists, I just return nil, the same as for any other error.<br>
<br>
Now I'm using the create-user function I wrote above, and I pass in a user name, and I get back nil. Does that mean there was a database error (not enough space left on drive) or does that mean there was already a user with the same name? I want to get additional information out of nil, but nil doesn't contain any information. It's nil!<br>
<br>
<a href="https://clojure-yap.blogspot.com/2013/07/nil-is-not-enough.html#more">Read more »</a>Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com2tag:blogger.com,1999:blog-2780729680834099800.post-4539616261345919262013-07-21T11:06:00.000-04:002013-07-21T19:38:49.017-04:00Setting up Friend: a few preliminaries<strong>[Revised: found out my first diagnosis and fix were incorrect, but eventually I tracked down the real answers.]</strong><br>
<br>
For my summer project, I'm developing a web site that local food banks can use to let people know what items they currently need. Long term, I want this to be accessible via smart phones, but for now I'm just getting started with the basics. I'm using the <a href="http://www.luminusweb.net/" target="_blank">Luminus</a> framework to kick things off since it's so convenient and well-documented.<br>
<br>
I initially set up my site with support for <a href="https://www.dailycred.com/?redirect=false">DailyCred</a>, which I only heard about because it was one of the template options for creating a new Luminus project. It seemed pretty easy to set up, and I got as far as redirecting users to DC and getting back the token, but at that point DC would complain that I was using an unknown client ID (even though it was a valid ID that worked correctly in their sandbox), and I'd be dead in the water. Finally I decided to fall back to a more conventional approach: today's project is to rip out all the DC stuff and replace it with <a href="https://github.com/cemerick/friend" target="_blank">Friend</a>. Partly this was frustration with DC, and partly it was because I just got done watching <a href="http://www.infoq.com/presentations/clojure-friend" target="_blank">this video</a>, and wanted to take Friend for a spin.<br>
<br>
<a href="https://clojure-yap.blogspot.com/2013/07/setting-up-friend-few-preliminaries.html#more">Read more »</a>Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com0tag:blogger.com,1999:blog-2780729680834099800.post-51447983816232975902012-01-11T18:41:00.002-05:002012-01-11T18:41:43.541-05:00Ah, a secret gateway into ClojureScriptI've been very interested in ClojureScript since it was first announced, but somehow I've never quite made it over that first hill. I think that may be <a href="http://clojure.com/blog/2012/01/11/announcing-clojurescript-one.html" target="_blank">about to change</a> though:<br />
<blockquote class="tr_bq">
<br />
ClojureScript One is a helpful resource for getting started with
ClojureScript. It is not a library or a framework. It is an example
with lots of documentation. We hope that by looking through this
example and reading the documentation we can remove the barriers that
are stopping you from experiencing how much fun ClojureScript
development can be. Once you have this experience, we think you will
be hooked. </blockquote>
<blockquote class="tr_bq">
You can find ClojureScript One on the web at
<a href="http://clojurescriptone.com/">http://clojurescriptone.com</a>.</blockquote>
I've downloaded the git repo and got the "Getting Started" stuff up and running in no time. Now if you'll excuse me, I have a REPL or two to play with...Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com0tag:blogger.com,1999:blog-2780729680834099800.post-3166371524335365652012-01-10T12:23:00.001-05:002012-01-10T12:23:13.721-05:00The perfect languageI was browsing through Planet Clojure the other day and saw a post about "<a href="http://lmf-ramblings.blogspot.com/2012/01/book-world-needs.html" target="_blank">The Book the World Needs</a>." Not to give away the plot, but the missing book is an introduction to functional programming for non-FP programmers.<br>
<br>
I'm not the guy to write that book, but reading that post reminded me of some of my early programming experiences, and helped me understand what it is that I find so appealing about Clojure.<br>
<br>
<br>
<a href="https://clojure-yap.blogspot.com/2012/01/perfect-language.html#more">Read more »</a>Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com1tag:blogger.com,1999:blog-2780729680834099800.post-5337181219317412862011-11-27T15:23:00.004-05:002011-11-27T15:37:51.505-05:00What I've learned from SaltyI spent the weekend hacking at my <a href="https://github.com/manutter51/salty" target="_blank">Salty</a> library for Clojure. Salty is a thin wrapper around the Selenium <a href="http://seleniumhq.org/docs/03_webdriver.html" target="_blank">WebDriver</a> framework, and it allows you to programmatically control a web browser like Firefox, as I've mentioned before. It turns out there is already a Clojure lib for WebDriver---<a href="https://github.com/semperos/clj-webdriver" target="_blank">clj-webdriver</a>---that is full-featured, easy to use, and very mature. For that reason, I'm probably not going to invest too much more effort in Salty. But that's fine: I mostly wanted to try this as a learning exercise, and clj-webdriver makes it easier for me to check my homework. Here's a few notes on what I think I got right and what I think I got wrong.<br>
<br>
<a href="https://clojure-yap.blogspot.com/2011/11/what-ive-learned-from-salty.html#more">Read more »</a>Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com0tag:blogger.com,1999:blog-2780729680834099800.post-60146170619834803572011-11-20T14:49:00.006-05:002011-11-20T16:44:44.267-05:00Re-formatting variable names(Series: From PHP to Clojure)<br>
<br>
Here's a simple problem: as part of my <a href="https://github.com/manutter51/salty" target="_blank">Salty</a> lib, I want a function that will take camel-case variable names, as used by Java, and convert them to the dash format that's idiomatic in Clojure. In other words, I want a function that will take the string "someVariableName" (camel case)and return "some-variable-name" (with dashes).<br>
<br>
<br>
<a href="https://clojure-yap.blogspot.com/2011/11/re-formatting-variable-names.html#more">Read more »</a>Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com4tag:blogger.com,1999:blog-2780729680834099800.post-15056476550171909252011-11-07T17:09:00.000-05:002011-11-07T17:09:00.698-05:00Salty: a Clojure wrapper for the Selenium Java WebDriverAfter my last post, I thought it might be fun to make a full-blown clojure library for working with Selenium WebDriver. I want to do a lot of Compojure/Noir development, and I can see where it might be handy to automate logging in and clicking things with Firefox and IE.<br />
<br />
Just to get started, I've set up a repository on github, and have written one quick and dirty test function.<br />
<br />
<script src="https://gist.github.com/1346333.js">
</script><br />
<br />
It's not really useful, it's just a quick spot-check you can run at the REPL to make sure everything's set up right. Make sure salty is in your classpath, and then, at the REPL, type (salty.impl/test-with-google). You should see Firefox start up, open up the main Google page, search for "clojure", and then quit. The output in your REPL should be:<br />
<pre>Original page title is Google
Page title after searching is clojure - Google Search
nil
</pre><br />
More to come...Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com2tag:blogger.com,1999:blog-2780729680834099800.post-16401051823716915852011-10-31T19:23:00.000-04:002011-10-31T19:23:06.373-04:00Clojure and the Firefox ZombieSince it's Halloween, I thought it might be fun to use Clojure to turn Firefox into a mindless zombie, slavishly obeying my every command. Muahahaha.<br>
<br>
<a href="https://clojure-yap.blogspot.com/2011/10/clojure-and-firefox-zombie.html#more">Read more »</a>Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com3tag:blogger.com,1999:blog-2780729680834099800.post-87214099157391297332011-10-29T15:13:00.000-04:002011-10-29T15:13:13.881-04:00A simple APII've been watching Rich Hickey's talk on <a href="http://www.infoq.com/presentations/Simple-Made-Easy">simplicity</a>, and trying to take it to heart. He's right: easy is easy, and simple is hard. It takes a lot of work, and careful use of the right tools, to end up with "simple."<div><br>
</div><div>So here's one tool (dare I say pattern?) that might be useful in building a simple API. I'm building on some posts and IRC conversations that I've run across, so most of this is not original with me, but I'm writing it down here for future reference.</div><div><br>
</div><div>In the spirit of classic "design pattern" methodology, here is the scenario we're trying to address. We need to write some functions that refer to some kind of state. The specific example I'm using is connecting to an IMAP server: I want to establish a connection, grab some message headers, selectively grab the message contents, and so on. Obviously, I don't want to negotiate a separate connection for each and ever IMAP operation I write code for. I want to connect once, and then share that connection with each of the functions that needs to use it.</div><div><br>
</div><div></div><a href="https://clojure-yap.blogspot.com/2011/10/simple-api.html#more">Read more »</a>Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com1tag:blogger.com,1999:blog-2780729680834099800.post-8527991911006968192011-10-29T09:07:00.000-04:002011-10-29T09:07:37.588-04:00Keeping up with starting outThere seems to be an impedance mismatch between the frequency with which I make posts about the easiest way to get started with Clojure, and the release of even easier ways to get started, so I'm going to just bag that thread. I'll just summarize my advice in a few simple bullet points:<br />
<br />
<br />
<ul><li>If you have to choose between adding clojure to an existing environment that's already heavily customized, and creating a fresh/clean environment via VirtualBox or some other equivalent, I recommend the fresh/clean environment. If you have a reasonably decent processor, it should be responsive enough to be useful, and the advice you find on the web will be a lot easier to apply if your OS is clean.</li>
<li>If you don't know emacs, it's worth learning just to get to use paredit.</li>
<li>If you like GUI IDE's, Eclipse + CounterClockwise works well.</li>
</ul>Feel free to add any other tips in the comments.Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com0tag:blogger.com,1999:blog-2780729680834099800.post-58428836230296316132011-10-29T08:59:00.000-04:002011-10-29T08:59:28.016-04:00Spring Security on CompojureI've moved away from using Spring Security for my Compojure/Noir-based web app, but I did eventually get an answer to my question on Stack Overflow, so if anyone's interested, they can look up the example in the answer.<br />
<br />
<a href="http://stackoverflow.com/questions/6901210/compojure-noir-using-spring-security-for-auth-auth">http://stackoverflow.com/questions/6901210/compojure-noir-using-spring-security-for-auth-auth</a>Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com0tag:blogger.com,1999:blog-2780729680834099800.post-88432684917565580382011-08-07T16:37:00.000-04:002011-08-07T16:37:10.645-04:00Using Spring Security with Clojure/Compojure/Noir: PreliminariesI don't know how to use Spring Security with Clojure web apps, but I'd like to learn how. I've got some clues, and I'm going to try and track them down and see how far I can get.<br />
<br />
The first obstacle to overcome is that there doesn't seem to be anything in clojars I can just grab. Fortunately leiningen prints out some detailed error messages, which I can use to manually install the jar files I need. First I'll grab the jar files from http://www.springsource.com/download/community. Just the 3.0.5 release is all I need. I unzip the file, which gives me a directory with a number of different jar files in it.<br />
<br />
Next, I cheat by editing my project.clj file to ask for a jar that doesn't exist. The <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">lein deps</span> command chugs along for a while, and then spews out a huge error dump, but with a little digging I can find this message somewhere in the middle:<br />
<br />
<pre>Unable to resolve artifact: Missing:
----------
1) org.springframework.security:spring-security-parent:jar:3.0.5.RELEASE
Try downloading the file manually from the project website.
Then, install it using the command:
mvn install:install-file -DgroupId=org.springframework.security -DartifactId=spring-security-parent -Dversion=3.0.5.RELEASE -Dpackaging=jar -Dfile=/path/to/file
</pre><br />
There's the magical incantation I need. I'll just cheat again by editing the suggested maven command so that it installs each of the jar files that I downloaded from springsource. I don't know yet which specific jar files I'll need, so I'll install them all.<br />
<br />
<pre>mvn install:install-file -DgroupId=org.springframework.security -DartifactId=spring-security-acl -Dversion=3.0.5.RELEASE -Dpackaging=jar -Dfile=./spring-security-acl-3.0.5.RELEASE.jar
mvn install:install-file -DgroupId=org.springframework.security -DartifactId=spring-security-aspects -Dversion=3.0.5.RELEASE -Dpackaging=jar -Dfile=./spring-security-aspects-3.0.5.RELEASE.jar
mvn install:install-file -DgroupId=org.springframework.security -DartifactId=spring-security-cas-client -Dversion=3.0.5.RELEASE -Dpackaging=jar -Dfile=./spring-security-cas-client-3.0.5.RELEASE.jar
mvn install:install-file -DgroupId=org.springframework.security -DartifactId=spring-security-config -Dversion=3.0.5.RELEASE -Dpackaging=jar -Dfile=./spring-security-config-3.0.5.RELEASE.jar
mvn install:install-file -DgroupId=org.springframework.security -DartifactId=spring-security-core -Dversion=3.0.5.RELEASE -Dpackaging=jar -Dfile=./spring-security-core-3.0.5.RELEASE.jar
mvn install:install-file -DgroupId=org.springframework.security -DartifactId=spring-security-ldap -Dversion=3.0.5.RELEASE -Dpackaging=jar -Dfile=./spring-security-ldap-3.0.5.RELEASE.jar
mvn install:install-file -DgroupId=org.springframework.security -DartifactId=spring-security-openid -Dversion=3.0.5.RELEASE -Dpackaging=jar -Dfile=./spring-security-openid-3.0.5.RELEASE.jar
mvn install:install-file -DgroupId=org.springframework.security -DartifactId=spring-security-taglibs -Dversion=3.0.5.RELEASE -Dpackaging=jar -Dfile=./spring-security-taglibs-3.0.5.RELEASE.jar
mvn install:install-file -DgroupId=org.springframework.security -DartifactId=spring-security-web -Dversion=3.0.5.RELEASE -Dpackaging=jar -Dfile=./spring-security-web-3.0.5.RELEASE.jar
</pre><br />
If I cd into the directory where I extracted the Spring Security jars, I can just cut and paste this code, and have each of the spring-security-* jars installed in my local .m2 directory, where leiningen can find them.<br />
<br />
Now I go back and edit project.clj, and add the core spring-security jar to my dependencies:<br />
<br />
<pre>(defproject mm2 "0.1.0-SNAPSHOT"
:description "FIXME: write this!"
:dependencies [[org.clojure/clojure "1.2.1"]
[noir "1.1.0"]
;; ADD SPRING SECURITY HERE:
[org.springframework.security/spring-security-core
"3.0.5.RELEASE"]]
:main mm2.server)
</pre><br />
Run <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">lein deps</span> and ... yup, the jar file is in lib/. It worked! Now I just need to figure out what other jar files I need (if any) and how to hook them into my clojure project. But that's a project for later.Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com0tag:blogger.com,1999:blog-2780729680834099800.post-67180065745107084072011-08-07T14:12:00.000-04:002011-08-07T14:44:51.379-04:00Setting up Emacs clojure modePicking up where we left off in <a href="http://clojure-yap.blogspot.com/2011/06/starting-from-scratch.html">Starting from Scratch</a>, we're next going to set up Emacs to be able to use clojure-mode for editing code, and to compile and run our Clojure programs for us. If you're new to Emacs, don't worry, we'll be taking this one step at a time.<br />
<br />
The plain Linux system we installed in the first post comes with Emacs version 23. Version 24 comes with an Emacs extension called <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">package.el</span>< that makes it easier to add new functionality to Emacs by downloading pre-built extensions from sites like <a href="http://marmalade-repo.org/">Marmalade</a>. Version 23 doesn't have this built in, so we'll have to add it by hand, which fortunately is not hard.<br />
<br />
<blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$ mkdir ~/.emacs.d</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$ cd ~/.emacs.d</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$ wget http://bit.ly/pkg-el23</span></blockquote><br />
This will pull down the <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">package.el</span> file and install it in your <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">.emacs.d</span> directory, which is the standard place to put extensions for Emacs. Having the file in the .emacs.d directory only makes it available to Emacs, though. To actually use it, we need to modify the <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">.emacs</span> startup file.<br />
<blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$ emacs ~/.emacs</span></blockquote>There may be some code already in the <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">.emacs</span> file, but we can safely skip over it for now. Go to the end of the file and add the following text:<br />
<br />
<blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">(add-to-list 'load-path "~/.emacs.d")</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">(require 'package) ;; loads package.el so we can use it</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">(add-to-list 'package-archives</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> '("marmalade" . "http://marmalade-repo.org/packages"))</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">(package-initialize)</span></blockquote>Quit Emacs and then open it up again. You should see the same opening screen as usual, but if there's a typo in the code you added to <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">.emacs</span>, you may see an error message instead. If that happens, open up <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">.emacs</span> again and double-check your typing, particularly single quotes and the dot between "marmalade" and the URL---it's not a comma. (The keyboard shortcut for opening a file is C-x-f, which is shorthand for Control-x followed by Control-f.)<br />
<br />
Once your <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">.emacs</span> file loads correctly, we can go on to the next step. We're going to use the Emacs command line, <i>aka</i> the "minibuffer," to actually install a couple of packages. To get to this command line, type M-x, which is shorthand for Meta-x. "Meta-x" means hold down the "meta" key (Alt key on Windows keyboards) while typing an "x". At the very bottom of your Emacs window, you should see the string "M-x" followed by a flashing cursor. Emacs is waiting for your command. (Note: if you mistype and need to get out of the minibuffer, type Ctrl-g.)<br />
<br />
We're going to give it a couple of commands. Let's start by installing paredit, a package that will automatically balance our parentheses for us.<br />
<blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">M-x package-install</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Install package: paredit</span></blockquote>Next, we'll install clojure mode, which uses paredit.<br />
<br />
<blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">M-x package-install</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Install package: clojure-mode</span></blockquote><span class="Apple-style-span" style="font-family: inherit;">Now we'll go back and make one last edit to </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">.emacs</span><span class="Apple-style-span" style="font-family: inherit;">.</span> Type the following at the end of the file:<br />
<blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">(defun turn-on-paredit () (paredit-mode 1))</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">(add-hook 'clojure-mode-hook 'turn-on-paredit)</span></blockquote>This will automatically turn on paredit mode whenever we edit a .clj file. Paredit mode is something people either love or hate because it forces you to keep your parentheses, braces, and square brackets matched. That's good, because otherwise you can get subtle bugs due to parentheses not closing where you thought, but sometimes paredit won't let you delete a single parenthesis even though you just want to move it someplace else.<br />
<br />
I'll tell you the paredit trick, though: cut and paste. You can cut and paste any of the parenthesis-like characters even if paredit won't let you backspace over them to delete them. Less convenient than a simple backspace, perhaps, but it's a small price to pay for the extra functionality and safety that paredit gives you, especially if you're new to LISPs and Clojure.<br />
<br />
We've got one last command to type at the command prompt:<br />
<blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$ lein plugin install swank-clojure 1.3.2</span></blockquote>This installs the code that allows Emacs to hook up to Clojure so that you can actually run a Clojure REPL inside Emacs. The command to start a Clojure REPL inside Emacs is <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">M-x clojure-jack-in</span>. The REPL takes a few minutes to come up -- no getting around that JVM startup time -- but after a little bit you should see the friendly <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">user=></span> prompt.<br />
<br />
And now you're good to go: you have a high-powered editing environment all hooked into the Clojure REPL, so you can edit code, and run it, and even edit it while you are running it. How cool is that?<br />
<br />
<span class="Apple-style-span" style="font-size: x-small;"><i>Comments, criticisms, corrections and questions are all welcome. Feel free to copy any or all of this post to use and/or improve for your own blog.</i></span>Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com0tag:blogger.com,1999:blog-2780729680834099800.post-60716899580661649192011-06-25T12:35:00.000-04:002011-07-23T18:45:13.929-04:00Starting from scratchI've been wanting to write about Clojure for some time now, and I've decided to do so from the perspective of a PHP programmer (that's me) making the transition to functional programming, using Clojure. I like to start at the beginning, so in this post, I'm going to set up a Clojure programming environment from scratch.<br>
<br>
[NOTE: Early feedback on this post suggests that I may be making things look harder than they really are. Clojure works just fine in any environment that runs Java, and can be developed using any editor or IDE. My goal in starting from scratch is purely didactic. I'm starting with a simple, bare-bones environment so that anyone who wants to follow along can easily do so without being distracted by issues like "I played with emacs a while ago and my .emacs file has some cruft in it" or "My classpath seems to be pointing at some old jar files I installed a couple years ago."<br>
<br>
If you're not interested in setting up a clean, minimal environment, feel free to skip ahead to the "Installing leiningen" section.]<br>
<br>
<a href="https://clojure-yap.blogspot.com/2011/06/starting-from-scratch.html#more">Read more »</a>Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com2tag:blogger.com,1999:blog-2780729680834099800.post-55920369501633192552011-06-20T18:55:00.000-04:002011-06-20T18:55:47.652-04:00I didn't think that would work.<div>Just saw a quick code snippet on the #clojure IRC channel. I didn't believe it would work at first, but apparently it does.<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">=> (defmacro rnd [] (rand-int 10))<br />
#'user/rnd<br />
=> (defn foo [] (rnd))<br />
#'user/foo<br />
=> (foo)<br />
8<br />
=> (foo)<br />
8<br />
=> (foo)<br />
8</span><br />
<br />
So every time you use your macro, it expands to a random number *at compile time*. The foo function is thus defined as a constant value, but it will be a different constant every time you re-load the code and run it.<br />
Not sure what that's useful for, but I bet it could do something cool.<br />
</div>Anonymoushttp://www.blogger.com/profile/13071213731127795604noreply@blogger.com0