Ruby blocks are anonymous functions with syntax sugar. You could write James' with_open method like this:
def with_open(stream, &f) f.call(stream) end The equivalent in Clojure is effectively the same: (defn with-open [stream f] (f stream)) On Oct 25, 9:31 am, James Reeves <[email protected]> wrote: > 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 <[email protected]> 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 [email protected] Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---
