On Mon, May 30, 2011 at 12:47 AM, iamcreasy <quazir...@gmail.com> wrote: >> Sort of. You can create a macro with defmacro, which like a special >> form controls the evaluation of its arguments instead of the arguments >> being evaluated first and the function only getting the results. >> Things like -> and defn are macros: > > That means, the difference of composite form and special form, is the > order / sequence of evaluation of arguments? right? > Composite form can be a function(list) or some other supported data > structures(Vector, map and set). Special form which looks a lot like a > funciton, is NOT a funciton / list / composite form at all.
I'd use "composite form" for anything that, in source code, is not an atom -- a list, vector, set, or map. Others may use it differently. The book you have seems to use it to mean just lists. > This also means, what is written on the book about special form > "Special forms are a particular type of composite form. For most > purposes, they are used very similarly to > a function call. The difference is that the first form of a special > form is not a function defined > somewhere, but a special system form that’s built into Clojure." > > is badly written or wrong, right? No. > Its not about being special form as a composite form, they are > different to begin with. Not really. > Its not about being 'built into clojure', its about how they work. It's both. >> 5. (foo bar baz) with foo not a special operator: the subform foo is >> looked up at compile time and if it's a macro, macro expansion is >> performed. The transformed code is then evaluated per these rules. > > I didn't understand this one.Is it about user defined function? No, macros. >> 6. (foo bar baz) with foo not a special operator or a macro. At >> compile time, code is generated to evaluate foo, bar, and baz at >> runtime and then apply foo as a function to the arguments bar and baz. > > I didn't understand this point too. An example would help. (def foo 42) Since 'def is a special operator, this is a special form and it has special evaluation rules. It ends up interning a Var named 'foo in the current namespace with the value 42. (defn bar [] 42) Since 'defn is not a special operator, the compiler checks the namespace for any Var visible in it named 'defn. It finds that 'clojure.core/defn is referred, and uses that. The object in that Var proves to be a macro, so the compiler expands it by calling it as a function with the rest of the form, unevaluated, as arguments. This produces something resembling (def bar (fn bar [] 42)) and this is a 'def special form, which ends up interning a Var named 'bar in the current namespace whose value is a function object which, when called with no arguments, returns the number 42. (bar) Since 'bar is not a special operator, the compiler checks the namespace for any Var visible in it named 'bar. It finds that the current namespace itself contains a Var named 'bar and uses that. The object in that Var proves to be a function, so the compiler converts this form into bytecode that calls the function. At runtime, when this executes, the function returns the number 42. >> (def bar baz) bar var interned baz eval'd, bar set >> (macro x y) macro is expanded expansion is eval'd > > Arn't they same? def is written withing clojure and when needed its > expanded. Not really. Special forms have special evaluation rules. The bytecode emitted can, in theory, be anything, and things can be done at compile time. In the case of def, a Var is interned as soon as the compiler even sees the form. If you didn't already have def you might be able to recreate it as a macro using some interop calls on *ns* to intern a Var. On the other hand if you didn't already have try you would not be able to recreate that with a macro at all. No combination of functions and macros compiles to bytecode that includes an exception handler unless it contains the try special form after all macroexpansion. >> 'def is definitely a symbol. > > If def is a symbol then it should evaluated to somthing?like, when I > write 'print' and press return key, I get > > #<core$print clojure.core$print@4b455d1c> > > but, in case of def, i get the following 'Error', > > #<CompilerException java.lang.Exception: Unable to resolve symbol: def > in this context (NO_SOURCE_FILE:0)> > > Isn't this concludes def is not a symbol cause its returning an error. No; 'def is a symbol but it's not bound to anything in the current namespace so you get the "unable to resolve" message. Meanwhile, 'print is bound to a function object from clojure.core. When you type print at the REPL it evaluates to the function object, which prints the way you saw. And if you quote, typing either 'def or 'print, you get the symbol itself back. If you (def def 42) and evaluate def you'll get 42 instead of the "unable to resolve" message. But (def ...) won't throw a "cannot cast Integer to IFn" message the way (42 ...) would, because the symbol 'def in operator position is always treated as a special operator rather than looked up. This is the other thing that would be different if def were a macro; if def were a macro you could shadow it locally with 42, and you'd get "cannot cast Integer to IFn" from a subsequent (def ...) form. > From you explanation what i got that, built in macros are called > special form and I can also create my custom macros, which will be > called special forms. is it right? Not really. Special forms and macros aren't the same, though they're similar in that they do some of their stuff at compile time and can't be passed to higher-order functions. Particularly significant is that a special operator in operator position effectively shadows all functions and macros that may have been given the same name, though you can still get at the latter by namespace-qualifying them or assigning them to locals and then calling the local or both. -- Protege: What is this seething mass of parentheses?! Master: Your father's Lisp REPL. This is the language of a true hacker. Not as clumsy or random as C++; a language for a more civilized age. -- 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