Function passed as parameter, its parameters number will not be validated when called.

50 views
Skip to first unread message

Aklscc

unread,
Nov 7, 2019, 12:55:47 AM11/7/19
to ClojureScript
Hello, everyone. I use ClojureScript as following:

(defn call-fn
 
[f]
 
(f 23 34))

(defn my-fn
 
[a]
 
(println a))

(call-fn my-fn)
;; => 23

Without any exception throwed. Why does this? Is it a bug?  

Alan Moore

unread,
Nov 7, 2019, 1:46:11 PM11/7/19
to ClojureScript
At the risk of being redundant, the Clojure version throws an exception:

user=> (call-fn my-fn)

ArityException Wrong number of args (2) passed to: user/my-fn  clojure.lang.AFn.throwArity (AFn.java:429)

Alan

Zane Shelby

unread,
Nov 7, 2019, 2:23:36 PM11/7/19
to clojur...@googlegroups.com
The short answer is that ClojureScript is compiled to JavaScript before being evaluated, and JavaScript is very permissive when it comes to the number of arguments provided to functions.

To show you there's no black magic going on here it helps to look at the JavaScript the compiler produces for your program. (One easy way to do that is to paste it into app.klipse.tech.) Here's what I get for your program:
cljs.user.call_fn = (function cljs$user$call_fn(f){ return f.call(null,(23),(34)); }); cljs.user.my_fn = (function cljs$user$my_fn(a){ return cljs.core.println.call(null,a); }); cljs.user.call_fn.call(null,cljs.user.my_fn);
my-fn only accepts one argument, but is called (via Function.prototype.call) with two. It turns out JavaScript functions, whether called directly, via Function.prototype.call, or via Function.prototype.apply ignore extra arguments. The fact that you've passed it into call-fn as an argument before calling it is red herring, turns out.

You can validate this for yourself in your browser's JavaScript console:
(function(x) { return x + 1; })(0,7)
⇒ 1

(function(x) { return x + 1; }).call(null, 0, 7)
⇒ 1

(function(x) { return x + 1; }).apply(null, [0, 7])
⇒ 1
JavaScript functions are also permissive in the other direction; missing arguments will be replaced with undefined:
(function(x) { return console.log(x); })()
undefined
⇒ undefined
 
(function(x) { return console.log(x); }).call(null)
undefined
⇒ undefined 
 
(function(x) { return console.log(x); }).apply(null, [])
undefined
⇒ undefined
Hope that helps!


--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to the Google Groups "ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/clojurescript/0c02f6ea-3b20-4356-9320-98594faf7986%40googlegroups.com.

Aklscc

unread,
Nov 7, 2019, 11:25:21 PM11/7/19
to ClojureScript
Good workaround! Thank you sincerely.

在 2019年11月8日星期五 UTC+8上午3:23:36,Zane Shelby写道:
To unsubscribe from this group and stop receiving emails from it, send an email to clojur...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages