Hacker News new | ask | show | jobs
by pugio 4065 days ago
Your point seems to be that macros allow for a slightly more natural syntax for certain things, but I can do pretty much the same thing in a language with a natural HOF syntax (Ruby):

  with_open_file filename do |f|
    do stuff with file
  end
And for your second example:

  # our 'macro' function
  def defclass(name, parent, &blk)
    k = Class.new(parent)
    k.instance_eval(&blk)
    Kernel.const_set(name, k)
  end

  defclass :Tiger, Animal do
    attr_accessor :age, :name
  end

Yes, macros allow for a superset of what you can reasonably accomplish with higher order functions, but I haven't yet seen a simple practical example of where the added power is useful. I'm sure it's nice to have, but there's something to be said about a language which generally gets you 95% of the way there using a simple set of built-in operations.
2 comments

Sure, ruby has nice syntax for lambda, but the entire point is not even having to worry about what goes into blocks and what not. Syntax is a bad excuse for abstraction. Lisp has higher order functions too, but a deceptively short (or "natural") syntax can easily sweep ugly semantics under the rug. I know no one would ever write your defclass hof anyways because of the extreme runtime overhead that causes. If you wanted to reimplement your defclass macro more efficiently, I don't see how you would be able to do so while not breaking all of a users code relying on that function. The point of a macro is so the implementation detail is hidden, and the interface doesn't have to change when you change the implementation. Lisp has higher order functions too. Hell, that's where ruby got it from. Higher functions have their uses, but they are not for abstracting patterns in code like macros are. They are for abstracting procedures in code on arguments received at runtime. The difference is macro expansion happens lexically, at compile time, while functions are part of the program at runtime.

If you haven't seen a practical example of what it's useful for, that's akin to the attitude of a C programmer not understanding the usefulness of higher order functions. They say, I get 95 percent of the way their with good old functions and function pointers. We would find that absurd, just as how I find the claim that a 'simple practical example of where added power of a macro is useful does not exist' is absurd

For example, see 'A unit testing framework' in 'practical common lisp' available online by Peter seibel. I can't possibly imagine how you'd be able to create a unit testing framework abstraction in Ruby as nice or efficient as the one presented with higher order functions in 26 lines of code. But it'd be cool if anyone could prove otherwise.

Notice that in your Ruby code you have to use quoted symbols like :Tiger and :age and :name, because you cannot extend Ruby's syntax with your own. Ruby has good metaprogramming facilities, but it's no substitute for a real macro system.