user=> (< 1 2 3 4)
true
user=> (>= 3 2 1)
true
Also, I am little bit confused about this behavior:
user=> (and true false)
false
user=> (apply and '(true false))
(clojure/let [and__175 true] (if and__175 (clojure/and false) and__175))
; doesnt return false, but expanded form
user=> (if (apply and '(true false)) :true :false)
:true
; this is always true, since form isn't nil or false
user=> (map and '(true false) '(false true))
((clojure/let [and__175 true] (if and__175 (clojure/and false) and__175))
(clojure/let [and__175 false] (if and__175 (clojure/and true) and__175)))
; forms again - not list of '(false false)
Is this expected behaviour? Or a bug?
Thank you for answering, Frantisek
"and" is a macro, not a function. It must be a macro because it has
to control the evaluation of it's arguments, so that any arguments
following an argument evaluating to "false" or "nil" are not evaluated
themselves, which is how the "&&" operator works in most languages.
The result is that the (and ...) expression will be expanded before
being passed to "apply".
HTH,
- J.
> Any comments on extending the number of parameters of '=' and 'not='?
Yes, I agree that would be a good Lisp-ish design.
You could also write your own, perhaps like this:
(defn all-eq
([] true)
([n] true)
([x & rest] (every? #(= x %) rest)))
Graham
Am 06.08.2008 um 22:55 schrieb Frantisek Sodomka:
> Testing:
> user=> (apply = 1 1 '(1 1))
> true
> user=> (apply = 1 1 '(1 2))
> false
>
> Interesting behavior of 'apply' with mixed parameters ;-)
I'm not sure I get your point. This is totally as expected, since
(apply = 1 1 '(1 1)) is equivalent to (= 1 1 1 1) which should
return true. Similar (= 1 1 1 2) should return false.
Sincerely
Meikel
Frantisek
I absolutely understand why one shouldn't apply a macro; however,
this change also makes it impossible to pass a macro as an argument,
which seems wrong to me. For example, I've been using
clojure.contrib.import-static, which allows one to import static
methods of a class into a namespace, like so:
(import-static org.apache.hadoop.hbase.util.Bytes
toString toBytes toInt toLong)
This makes toBytes, toInt, etc., "top-level" members in the current
namespace. I'm then able to pass them around like regular functions,
which is clearly very handy.
That's a simple example, and I'm sure that import-static could be
implemented using regular functions, but that's besides the point.
As long as a macro is being used in function position (and not being
applied), is there any particular harm to allowing them to be passed
as arguments? By all means, ensure that they're not applied, but
doing more than that seems unnecessarily restrictive.
- Chas
On Thu, Aug 7, 2008 at 8:02 AM, Chas Emerick <ceme...@snowtide.com> wrote:
> I absolutely understand why one shouldn't apply a macro; however,
> this change also makes it impossible to pass a macro as an argument,
> which seems wrong to me.
Whether you use (fn [f] (apply f ...)) or (fn [f] (f ...)), you're
still applying a function at runtime, because "f" is an argument in
both of these expressions. The presence of "apply" isn't what makes
passing in macros wrong; it's when they are applied that matters.
For example, I've been using
> clojure.contrib.import-static, which allows one to import static
> methods of a class into a namespace, like so:
>
> (import-static org.apache.hadoop.hbase.util.Bytes
> toString toBytes toInt toLong)
That could be implemented as a function, as you suggest -- the macro
is just sugar. (I like that clojure/import and clojure/refer are
functions, not macros, for this very reason -- wishing to save a few
quote-marks and brackets isn't worth adding a macro and losing a
first-class function.)
> That's a simple example, and I'm sure that import-static could be
> implemented using regular functions, but that's besides the point.
> As long as a macro is being used in function position (and not being
> applied), is there any particular harm to allowing them to be passed
> as arguments? By all means, ensure that they're not applied, but
> doing more than that seems unnecessarily restrictive.
The sticking point is that macros are evaluated at compile-time;
passing macros to be called in higher-order functions would require
that macros were evaluated at runtime. In effect, the higher-order
function would need to recompile part of itself dynamically in order
to correctly apply the macro.
Best,
Graham
Even better would be "distinct?"
> Just a suggestion...
>
> Frantisek
Randall Schulz
> The sticking point is that macros are evaluated at compile-time;
> passing macros to be called in higher-order functions would require
> that macros were evaluated at runtime. In effect, the higher-order
> function would need to recompile part of itself dynamically in order
> to correctly apply the macro.
>
> Best,
> Graham
FWIW, Rich set me straight in irc :-)
I had been using macros defined by import-static in a code path that
was eval-ing certain forms, which was silently making the macros look
like they were behaving like first-class functions.
- Chas