do special forms use only special-symbols? - clojure

executing the following commands in REPL
(symbol-special? 'do) ;=> true
(type 'do) ;=> Symbol
(doc do) ;=>.. it is a Special form...
and the same thing for let
(symbol-special? 'let) ;=> FALSE
(type 'let) ;=> Symbol
(doc let) ;=>.. it is a Special form...
I know let is a macro that uses the special-symbol let*, is there a relationship between special-symbols and special-forms?
regards,

"Special forms" are those that receive special handling from the compiler. These are precisely the forms that have a "special symbol" in operator position.
let is described as a special form in the documentation, because let* is considered to be an implementation detail and users are encouraged to think of let as a basic building block of the language. At least that's my understanding.
(NB. users of other Lispy languages may attach somewhat different meanings to the two terms. This usage is established in the Clojure community.)

Related

why are compojure routes defined as macros?

for example the Luminus website states that
Compojure route definitions are just functions that accept request
maps and return response maps...
(GET "/" [] "Show something")
...
But compojure routes are not functions
(defmacro GET "Generate a `GET` route."
[path args & body]
(compile-route :get path args body))
One can use the function make-route that returns a functions, but does not allow for destructuring. So as a function you can not use compojure's special syntax for destructing (i.e the vector) but does this stop any form of destructuring? Does the macro from given them a performance increase?
(make-route :get "/some_path" some_handler)
Couldn't the destructing syntax be passed to the function using a macro wrapper?
One reason macros are used is so the user can write function and symbol names without having to quote everything. Take this example from the Clojure Cookbook:
; Routing
(defroutes main-routes
(GET "/" [] (index))
(GET "/en/" [] (index))
(GET "/fr/" [] (index-fr))
(GET "/:greeting/" [greeting] (view greeting)))
All of the index* symbols, plus view and greeting would have to be quoted if GET were a function:
; Routing
(defroutes main-routes
(GET "/" [] '(index))
(GET "/en/" [] '(index))
(GET "/fr/" [] '(index-fr))
(GET "/:greeting/" '[greeting] '(view greeting)))
Since function arguments are evaluated before the function is invoked, (index) et al would be evaluated as soon as the form was read. Also, the greeting arg will be changing on each HTTP request, so it obviously is not known ahead of time.
The macro also takes care of all the destructuring magic which is not (normally) possible with a regular function.
The thing which is often confusing (and is not well explained to beginners) is that a line like:
(GET "/:greeting/" [greeting] (view greeting))
is not normal "Clojure code". Instead, it is a type of shorthand (Domain-Specific Language or DSL to be precise) that the GET macro will ingest and use as instructions on how to generate "legal" Clojure code. The DSL is normally much shorter, simpler, & more convenient for a human than the final generated code, just as Clojure is much shorter, simpler, & more convenient than the Java Bytecode produced by the Clojure compiler, or the machine assembly language code eventually produced by the JVM.
In short, each macro is a "pre-compiler" that turns the DSL into plain Clojure, which is then ingested by the Clojure compiler to generate Java bytecode.
Having said that, it could be re-arranged to put all of the macro magic into the defroutes macro so that the GET symbol was neither a function nor a macro, but just a type of marker like the :get keyword in the implementation. As a user, these kinds of implementation details normally don't matter much.
Update
It is best to use macros only when a function won't work or is very awkward. The deciding factor is usually if one wants to use bare (unquoted) symbols, but not evaluate them in advance. Core Clojure itself uses macros for many constructs that are "built-ins" in other languages, including defn, for, and, or, when, and others.
Also note that a macro cannot do some things a function can, such as being a parameter to a higher-order function like filter.
In summary, a function defines a behavior. A macro defines a language extension.

How to test if a symbol points to a special form or a macro

I need a function that can tell whether a symbol is pointing to a special form or a macro.
I found the function? function in the clojure.test namespace, so could use that, but I'm hesitant to use it because it seems to be intended only for testing purposes. Is it okay to use it for normal code? If not, how can I accomplish my goal.
As noted the comments, fn? does not work because it only works on functions themselves, not the symbols that point to them.
If it does what you want, use it. It's in clojure.test because it wasn't expected to be useful for non-test code, but if it's the best function for your particular use case, there's no reason to hamper yourself just because of where the function is located. In other words, clojure.test is separate from clojure.core for organization, not because it should only ever be used for tests.
you can find all special form, :-)
(defn special-symbol?
[s]
(contains? (. clojure.lang.Compiler specials) s))

Obsolete-ing Symbols in Clojure

Is there any way to mark a symbol as obsolete in Clojure?
I could use something like this from Lein which works well.
https://github.com/technomancy/leiningen/blob/1.x/src/leiningen/core.clj#L13
But the it only emits its warning when a function is called. I'd really like the compiler to pick this up at the time code is compiled, rather than when it is called.
Of course, I could just not define the symbol, which the compiler would then pick
up, but this robs me of the ability to provide any information, such as why, or when
the symbol has been deprecated.
All of this is for a DSL where deprecation and obsolescence of terms is going to happen at a reasonable rate.
There's already something in the comments about using macros, but as someone noted this precludes using the function as a HOF. You can get around this, although it may be that the cure isn't worse than the disease. For example, imagine your function is
(defn foo* [x y] (+ x y))
Then instead of writing
(defmacro foo [x y] (warn) `(foo* x y))
(foo 1 2)
(map foo [5 6] [7 8])
You can make the macroexpansion return a function, which of course can be used like any other:
(defmacro foo [] (warn) `foo*)
((foo) 1 2)
(map (foo) [5 6] [7 8])
Probably not worth the awkwardness, but does provide a way to complain whenever the deprecated feature is used while still keeping the possibility of HOF usage.
It really depends on how your DSL is designed. If you can design your DSL such that each form must be wrapped in a go or something similar call then you could write this go macro which does something like this:
macroexpand-all (from clojure.walk) to the passed form
Use postwalk (from clojure.walk) on the above returned form and check if any of the symbols encountered are deprecated by probably looking at some global list of deprecated symbols. You may need to do resolve on the symbols to get namespace qualified name of the symbol.
If any deprecated symbol found, the print message.
Return the input form as it is.
This go macro then can be used for other pre-processing of your DSL as this is the entry point for your DSL execution.
NOTE: You may need to come up with solution where user uses same name for his/her own symbol from one of the deprecated symbols, but again this may not be needed depends on your DSL design.

How can you type hint within the threading (->) macro?

I have some Clojure code that is trying to interop through a couple layers of Java code (in this case, java.nio.Path by way of java.nio.file.WatchEvent<?>:
(defn unroll-event
[^WatchEvent event]
{ :kind (.kind event)
:context (.context event)
:path (-> event .context .toAbsolutePath .toString)})
In this code, I have type hinted event, so I would think it should be able to figure out what .context is supposed to return, and as such, be able to figure out what .toAbsolutePath and .toString do. I think in this case, since .context is defined has returning a generic type T, I am wondering if I can type hint the call to .context. I've tried just prepending ^java.nio.file.Path to .context, and ^Path and ^String to .toAbsolutePath and toString, respectively, but I still get the warnings:
Reflection warning, junkcode/core.clj:28 - reference to field toAbsolutePath can't be resolved.
Reflection warning, junkcode/core.clj:28 - reference to field toString can't be resolved.
Is there something I can do in this case? Is it because -> is a macro and there are special rules for type hinting within that?
(-> x .blah ^String .bar) expands to, basically, (^String .bar (.blah x)), which is clearly not where you want the hint. The point is that type-hinting does not have special behavior in any context (eg, macros): it's just metadata applied to the source-code symbols. In your example ->, there is no place that you can put metadata on the input form that will cause it to be where you want in the output form. So you need to write some other form, like (-> ^Path (.context event) .toAbsolutePath str), for example.
Also, Clojure's inferencer doesn't know anything about generic types, so a method-returning-T gets treated as a method-returning-Object, which explains why you need to hint at all in here.
I don't know if this has always been the case, but in Clojure 1.4.0, 1.5.1, and 1.6.0, you can type-hint at any point in -> as long as you use parentheses:
user=> (set! *warn-on-reflection* true)
true
user=> (fn [^java.nio.file.WatchEvent e]
(-> e ^java.nio.file.Path .context .toAbsolutePath))
Reflection warning, /private/var/folders/9_/wdph6m796zzc8trzcbtcmhrn5bjpt0/T/form-init8364673644863044068.clj:1:35 - reference to field toAbsolutePath on java.lang.Object can't be resolved.
#<user$eval1995$fn__1996 user$eval1995$fn__1996#8128f39>
user=> ; but no warning if we do
user=> (fn [^java.nio.file.WatchEvent e]
(-> e ^java.nio.file.Path (.context) .toAbsolutePath))
#<user$eval1999$fn__2000 user$eval1999$fn__2000#4747e32a>
The only difference is the parens around .context.

General syntax of multimethods

I apologize if the question is trivial, but some googling is not leading me anywhere. What is the general syntax of defmulti and defmethod? I can write simple multimethods, but I am not sure where I can put the docstring, pre and post conditions, metadata and so on.
I am actually interested in ClojureScript more than in Clojure, so if there are differences between the two, please tell me.
In a REPL you can use the doc function to get the function arguments and (most of the time) an explanation of the options. As for ClojureScript, these two functions are macros, which means they are expanded at compile time and should behave exactly as they do in regular Clojure. That is, as long as ClojureScript can handle the code the macro generates.
user=> (doc defmulti)
-------------------------
clojure.core/defmulti
([name docstring? attr-map? dispatch-fn & options])
Macro
Creates a new multimethod with the associated dispatch function.
The docstring and attribute-map are optional.
Options are key-value pairs and may be one of:
:default the default dispatch value, defaults to :default
:hierarchy the isa? hierarchy to use for dispatching
defaults to the global hierarchy
nil
user=> (doc defmethod)
-------------------------
clojure.core/defmethod
([multifn dispatch-val & fn-tail])
Macro
Creates and installs a new method of multimethod associated with dispatch-value.
nil
At Clojuredocs: defmulti, defmethod.
If you don't find the examples there detailed enough, you might consider adding your own (once you've gotten all your questions answered).