Clojure

Function literals behavior differ from that of fns

Details

  • Type: Defect Defect
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Declined
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:

Description

((fn [] true)) ; true
(#(true)) ; classcast exception

((fn [])) ; nil
(#()) ; ()

(some (fn [_]_) [nil false 0 1]) ; 0
(some #(%) [nil false 0 1]) ; NPE

Activity

Hide
Víctor M. Valenzuela added a comment -

You're right - satisfying my request would require to change the average use of this feature to #((some_fn %1 %2)) rather than just #(some_fn %1 %2), if we wanted #(true) to be valid. Which indeed would be barely handy.

Thank you.

Show
Víctor M. Valenzuela added a comment - You're right - satisfying my request would require to change the average use of this feature to #((some_fn %1 %2)) rather than just #(some_fn %1 %2), if we wanted #(true) to be valid. Which indeed would be barely handy. Thank you.
Hide
Tassilo Horn added a comment -

The reader docs at http://www.clojure.org/reader say that #() is not a replacement for (fn [] ...). You can't make it more equivalent to fn without making it much harder to understand. Let me explain that with an example.

(defn get-time []
  (System/currentTimeMillis))

(#(get-time)) ;; What's the result?

What's the result of the funcall above? Clearly, right now, it is the current system time.

So if we decided to allow to write #(true) as an alternative to (constantly true) [which is a varargs fn] or #(do true) [which is a fn of zero args], then valid values of #(get-time) where both the current system time but also the function object for get-time. Functions are values, too.

Ok, one could say that in the case of a function, #(function) is always a call, but it would make it harder to reason about what the code does for not much benefit.

Show
Tassilo Horn added a comment - The reader docs at http://www.clojure.org/reader say that #() is not a replacement for (fn [] ...). You can't make it more equivalent to fn without making it much harder to understand. Let me explain that with an example.
(defn get-time []
  (System/currentTimeMillis))

(#(get-time)) ;; What's the result?
What's the result of the funcall above? Clearly, right now, it is the current system time. So if we decided to allow to write #(true) as an alternative to (constantly true) [which is a varargs fn] or #(do true) [which is a fn of zero args], then valid values of #(get-time) where both the current system time but also the function object for get-time. Functions are values, too. Ok, one could say that in the case of a function, #(function) is always a call, but it would make it harder to reason about what the code does for not much benefit.
Hide
Víctor M. Valenzuela added a comment - - edited

It makes sense. However (and correct me if I'm wrong) there should be little problem in making them fully equivalent to fns, resulting in a more concise and consistent API.

Please consider re-opening the issue as a feature request.

Regards - Víctor.

Show
Víctor M. Valenzuela added a comment - - edited It makes sense. However (and correct me if I'm wrong) there should be little problem in making them fully equivalent to fns, resulting in a more concise and consistent API. Please consider re-opening the issue as a feature request. Regards - Víctor.
Hide
Tassilo Horn added a comment -

This is no defect. Function literals must have a function (or macro or special form) as first symbol.
So your examples should be written like so:

user> (#(do true))
true
user> (#(do))
nil
user> (some #(do %) [nil false 0 1])
0
Show
Tassilo Horn added a comment - This is no defect. Function literals must have a function (or macro or special form) as first symbol. So your examples should be written like so:
user> (#(do true))
true
user> (#(do))
nil
user> (some #(do %) [nil false 0 1])
0

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: