I don't think that's a very good example of what macros can do. As you
point out, you can do much the same thing in Ruby with blocks:

with_open(MyStream.new) do |stream|
  stream.write "Hello"
end

In Clojure, blocks are analogous to anonymous functions. So the
equivalent Clojure would be:

(with-open (MyStream.)
  (fn [stream]
    (.write stream "Hello")))

You could use a macro to make this more concise:

(with-open [stream (MyStream.)]
  (.write stream "Hello"))

But whilst this is useful, this doesn't really demonstrate why macros
are so powerful. Macros are useful because they automatically
rearrange your source code into something else. They're most similar
to the Ruby 'eval' function, but operate of data structures rather
than strings.

For example, the macro '->' changes this:

(-> x (foo y) (bar z))

Into this:

(foo (bar x z) y)

- James

On Oct 25, 1:55 pm, Daniel Bush <dlb.id...@gmail.com> wrote:
> hi,
> I'm new to lisp/clojure
> in general.  I was reading the free whitepaper from Amit
> Rathore's 'Clojure in Action' where he gives a simple
> example on macros.
>
> In the example on page 9 he shows how you might do an
> audited connection in java:
>
> public void addExpense(long userId, Date date, BigDecimal amount) {
>    AuditLogger.logLookup(userId, AuditCode.ADD_EXPENSES);
>    ExpensesConnection connection = new ExpensesConnection(userId);
>    connection.saveNewExpense(date, amount);
>    connection.flush();
>    connection.close();
>
> }
>
> In clojure he shows a macro (without showing the code[1])
> that boils it down to:
>
> (defn add-expense [user-id date amount]
>   (with-audited-connection [user-id connection]
>     (save-new-expense connection date amount)))
>
> So in ruby you can be pretty concise here - in fact
> I differ with the author who says it isn't as good:
>
> def add_expense user_id , date , amount
>   with_audited_connection(user_id,'audit code') do |conn|
>     conn.save_new_expense date , amount
>   end
> end
>
> where with_audited_connection might be something like:
>
> def with_audited_connection user_id , audit_code
>   puts "logging conn for '#{user_id}' (#{audit_code})"
>   conn = ... # Get a connection.
>   yield conn # Expose conn in block - see above.
>   puts "closing conn or whatever"
> end
>
> ('puts' just means print to stdout)
>
> The second function above organises the connection 'conn'
> and then yields it for use elsewhere in a block (see the
> do-block in the first function).  After that block finishes,
> the yield returns and the the 2nd function tidies up and
> does whatever else it needs to.
>
> Bear in mind, I'm really new to lisp in general.
> So is 'connection' in
>   (with-audited-connection [user-id connection] ... )
> being filled in by the macro or is the example assuming that
> 'connection' has already been defined elsewhere?
> Can clojure do something like the 'yield' in the ruby
> example above (which I think is one of ruby's strengths
> coming from smalltalk)?
>
> I know you might say something like: "go learn some lisp
> and macros and you'll know what the author is trying to
> say", but I was hoping for just a quick indication on what is
> going on here - I'll continue learning clojure in the
> background anyway so I guess it'll eventually twig.
>
> Cheers,
> Daniel Bush
>
> [1] I know the example is just there to whet the appetite
> and is not part of a particular lesson or chapter.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to