In what way are Clojure maps functions? Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern) Data science time! April 2019 and salary with experience The Ask Question Wizard is Live!What's the difference between a method and a function?var functionName = function() vs function functionName() What is the scope of variables in JavaScript?Set a default parameter value for a JavaScript functionScala vs. Groovy vs. ClojureWhat is the difference between call and apply?What does the exclamation mark do before the function?Map to accept singular or collectionDon't know how to create ISeq from clojureHow to use reduce and into properly
What's the difference between using dependency injection with a container and using a service locator?
What documents does someone with a long-term visa need to travel to another Schengen country?
Can 'non' with gerundive mean both lack of obligation and negative obligation?
Can a Wizard take the Magic Initiate feat and select spells from the Wizard list?
2 sample t test for sample sizes - 30,000 and 150,000
How to make an animal which can only breed for a certain number of generations?
Marquee sign letters
Will I be more secure with my own router behind my ISP's router?
Does the Pact of the Blade warlock feature allow me to customize the properties of the pact weapon I create?
What could prevent concentrated local exploration?
When does Bran Stark remember Jamie pushing him?
Is my guitar’s action too high?
How to get a single big right brace?
Meaning of "Not holding on that level of emuna/bitachon"
Married in secret, can marital status in passport be changed at a later date?
Who's this lady in the war room?
Kepler's 3rd law: ratios don't fit data
What is the definining line between a helicopter and a drone a person can ride in?
Pointing to problems without suggesting solutions
Is Bran literally the world's memory?
Assertions In A Mock Callout Test
How to ask rejected full-time candidates to apply to teach individual courses?
What came first? Venom as the movie or as the song?
Raising a bilingual kid. When should we introduce the majority language?
In what way are Clojure maps functions?
Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)
Data science time! April 2019 and salary with experience
The Ask Question Wizard is Live!What's the difference between a method and a function?var functionName = function() vs function functionName() What is the scope of variables in JavaScript?Set a default parameter value for a JavaScript functionScala vs. Groovy vs. ClojureWhat is the difference between call and apply?What does the exclamation mark do before the function?Map to accept singular or collectionDon't know how to create ISeq from clojureHow to use reduce and into properly
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
In his talk "Maybe not" Rich Hickey states:
maps are (mathematical) functions!
in Clojure, we can directly write, and invoke
(:a 1 :b 2 :b) => 2
However I have the feeling that they are not in fact first class Clojure functions, or are they?
I can call the map with a keyword, or the other way around:
user=> (:b :a 1 :b 2 :c 3)
2
user=> (:a 1 :b 2 :c 3 :b)
2
But I can't use apply either way it seems:
user=> (apply #(:b %) :a 1 :b 2 :c 3)
ArityException Wrong number of args (3) passed to: user/eval1762/fn--1763 clojure.lang.AFn.throwArity (AFn.java:429)
user=> (apply #(:a 1 :b 2 :c 3 %) :b)
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:542)
And neither can I apply the keyword directly to the map:
user=> (apply :a 1 :b 2 :c 3 :b)
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:542)
So are they functions only in the mathematical sense, or is there more to them in the sense of applying a keyword similar to a "normal" clojure function?
function clojure
add a comment |
In his talk "Maybe not" Rich Hickey states:
maps are (mathematical) functions!
in Clojure, we can directly write, and invoke
(:a 1 :b 2 :b) => 2
However I have the feeling that they are not in fact first class Clojure functions, or are they?
I can call the map with a keyword, or the other way around:
user=> (:b :a 1 :b 2 :c 3)
2
user=> (:a 1 :b 2 :c 3 :b)
2
But I can't use apply either way it seems:
user=> (apply #(:b %) :a 1 :b 2 :c 3)
ArityException Wrong number of args (3) passed to: user/eval1762/fn--1763 clojure.lang.AFn.throwArity (AFn.java:429)
user=> (apply #(:a 1 :b 2 :c 3 %) :b)
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:542)
And neither can I apply the keyword directly to the map:
user=> (apply :a 1 :b 2 :c 3 :b)
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:542)
So are they functions only in the mathematical sense, or is there more to them in the sense of applying a keyword similar to a "normal" clojure function?
function clojure
2
If you use(apply #((fn [x] x) %) :b)
or(apply #(:b %) (fn [x] x))
to substitute an explicit 1-arity function in the places where you're currently passing maps, you get the same errors -- demonstrating that the problem is not about maps' function-ness, but about the usage patterns themselves.
– Charles Duffy
Mar 22 at 15:22
add a comment |
In his talk "Maybe not" Rich Hickey states:
maps are (mathematical) functions!
in Clojure, we can directly write, and invoke
(:a 1 :b 2 :b) => 2
However I have the feeling that they are not in fact first class Clojure functions, or are they?
I can call the map with a keyword, or the other way around:
user=> (:b :a 1 :b 2 :c 3)
2
user=> (:a 1 :b 2 :c 3 :b)
2
But I can't use apply either way it seems:
user=> (apply #(:b %) :a 1 :b 2 :c 3)
ArityException Wrong number of args (3) passed to: user/eval1762/fn--1763 clojure.lang.AFn.throwArity (AFn.java:429)
user=> (apply #(:a 1 :b 2 :c 3 %) :b)
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:542)
And neither can I apply the keyword directly to the map:
user=> (apply :a 1 :b 2 :c 3 :b)
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:542)
So are they functions only in the mathematical sense, or is there more to them in the sense of applying a keyword similar to a "normal" clojure function?
function clojure
In his talk "Maybe not" Rich Hickey states:
maps are (mathematical) functions!
in Clojure, we can directly write, and invoke
(:a 1 :b 2 :b) => 2
However I have the feeling that they are not in fact first class Clojure functions, or are they?
I can call the map with a keyword, or the other way around:
user=> (:b :a 1 :b 2 :c 3)
2
user=> (:a 1 :b 2 :c 3 :b)
2
But I can't use apply either way it seems:
user=> (apply #(:b %) :a 1 :b 2 :c 3)
ArityException Wrong number of args (3) passed to: user/eval1762/fn--1763 clojure.lang.AFn.throwArity (AFn.java:429)
user=> (apply #(:a 1 :b 2 :c 3 %) :b)
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:542)
And neither can I apply the keyword directly to the map:
user=> (apply :a 1 :b 2 :c 3 :b)
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:542)
So are they functions only in the mathematical sense, or is there more to them in the sense of applying a keyword similar to a "normal" clojure function?
function clojure
function clojure
asked Mar 22 at 13:56
ArneArne
1,67921738
1,67921738
2
If you use(apply #((fn [x] x) %) :b)
or(apply #(:b %) (fn [x] x))
to substitute an explicit 1-arity function in the places where you're currently passing maps, you get the same errors -- demonstrating that the problem is not about maps' function-ness, but about the usage patterns themselves.
– Charles Duffy
Mar 22 at 15:22
add a comment |
2
If you use(apply #((fn [x] x) %) :b)
or(apply #(:b %) (fn [x] x))
to substitute an explicit 1-arity function in the places where you're currently passing maps, you get the same errors -- demonstrating that the problem is not about maps' function-ness, but about the usage patterns themselves.
– Charles Duffy
Mar 22 at 15:22
2
2
If you use
(apply #((fn [x] x) %) :b)
or (apply #(:b %) (fn [x] x))
to substitute an explicit 1-arity function in the places where you're currently passing maps, you get the same errors -- demonstrating that the problem is not about maps' function-ness, but about the usage patterns themselves.– Charles Duffy
Mar 22 at 15:22
If you use
(apply #((fn [x] x) %) :b)
or (apply #(:b %) (fn [x] x))
to substitute an explicit 1-arity function in the places where you're currently passing maps, you get the same errors -- demonstrating that the problem is not about maps' function-ness, but about the usage patterns themselves.– Charles Duffy
Mar 22 at 15:22
add a comment |
3 Answers
3
active
oldest
votes
Maps are functions of keys, as in your first two examples. Maps implement IFn
interface just like "regular" Clojure functions.
The reason apply
doesn't work in your examples is due to the "sequence" arguments being passed in the second position.
(apply #(:b %) :a 1 :b 2 :c 3)
In that example, the map argument is being turned into a sequence of key/value vectors/tuples, so they can be applied to #(:b %)
(which wouldn't work anyway because that anonymous function only takes one argument). This is how the map would look as it's being turned into a sequence and applied as arguments to the function:
user=> (seq :a 1 :b 2 :c 3)
([:a 1] [:b 2] [:c 3])
This second example doesn't work because :b
is not a sequence — it's a single keyword. This works though:
user=> (apply :a 1 :b 2 :c 3 [:b])
2
Note that calling a map-as-function with apply
and a sequence of keywords doesn't really make practical sense though.
add a comment |
A mathematical function is a set of ordered pairs such that there are no distinct pairs with the same first element. A mathematical function so defined takes only one argument.
Clojure maps are self-evidently mathematical functions, since the there are no distinct key-value pairs with the same key. Moreover, Clojure maps have a finite domain (set of keys
) and range/co-domain (set of values
).
As @TaylorWood has stated, Clojure maps are Clojure functions because they implement clojure.lang.IFn. They do so as operators yielding the value for a given key, so consistent with their interpretation as mathematical functions.
Your apply
syntax is wrong. You can write
user=> (apply :a 1, :b 2 [:a])
1
or
user=> (apply :a 1, :b 2 :a [])
1
You can supply some of the arguments for the function (the first argument to apply
) inline. The remainder comprise the sequence that is the last argument to apply
. Since there is exactly one argument here, we can put it inline or alone in the terminal sequence.
Similar considerations apply to the use of keywords as arguments.
Reply to @AlanThompson's comments
I've listened to and read Rich's talk that the question refers to. My definition of a function agrees with his.
My statement that "A mathematical function so defined takes only one argument" is self evidently correct.
You could contend that my definition isn't the conventional one. But even that is false. If you read the Multivariate_function part of the Wikipedia article we both refer to, you will find
More formally, a function of n variables is a function whose domain is
a set of n-tuples
...
When using function notation, one usually omits the parentheses
surrounding tuples, writingf(x1 , x2)
instead off((x1 , x 2))
.
In other words, the idea that a (mathematical) function takes several arguments is a harmless informality that allows simpler notation.
Where does that leave programming languages? Most of them have functions of any arity: in Clojure's case, any finite set of arities, including an infinite one.
The simplest way to regard Clojure functions is that they take an inline sequence of arguments, perhaps an empty one. It would be possible to formulate mathematical functions in this way: mappings from sequences of things to things. But it just isn't done.
Many functions in math take more than 1 arg:z=2x+3y
being a simple example.
– Alan Thompson
Mar 22 at 17:27
@AlanThompson In that case, the first element in your order pair would simply be another ordered pair -- i.e., ((x,y), z)
– Nathan Davis
Mar 22 at 19:29
It is not that simple. 6 DOF models for aircraft, motorcycles, etc measure both position & rotation (x2) in 3D (x3), and may include derivatives 0, 1 and 2 (x3). That makes 18 input arguments to a function!
– Alan Thompson
Mar 22 at 20:24
@AlanThompson That is quite simple, mathematically. The function is a set of ordered pairs whose first element are 18-tuples. Unpleasant and offensive to you as a programmer, but nothing wrong with it in theory. All functions, of any number of arguments, can be viewed in this way.
– amalloy
Mar 23 at 0:32
I am simply trying to refute the incorrect statement, "A mathematical function so defined takes only one argument". This will mislead people. A generalized function takes N inputs and produces M outputs: en.wikipedia.org/wiki/Function_(mathematics)#Arrow_notation.
– Alan Thompson
Mar 23 at 3:28
add a comment |
I'm not sure what the practical goal of this question is, but it is interesting from an academic point of view.
The keyword "function" :b
in the following is a function of 1 argument:
(:b :a 1 :b 2) => 2
It is like this function:
(defn get-b [m] (get m :b)) ; takes a single map arg
(get-b :a 3 :b 33) ; only 1 arg, so no problem
=> 33
The special form apply
re-writes the function call from having a single collection argument to having multiple, individual args. Comparing before & after we get:
(apply some-fn [1 2 3] ) ; using apply
(some-fn 1 2 3 ) ; without apply (note missing square brackets!)
So, apply
allows you to "spread" args from a collection as if you had typed them as separate, individual args in the function call. If your collection has only 1 element, using apply has little effect:
(apply :b [:a 3 :b 33] ) ; a collection of 1 element
(:b :a 3 :b 33 ) ; only 1 arg, so no problem
Because the function :b takes only 1 arg, the following won't work:
(apply #(:b %) [:a 1 :b 11 :a 2 :b 22 :a 3 :b 33]) ; takes only 1 arg, not 3 args
However, you can invoke the 1-arg function :b
multiple times using map
or mapv
:
(mapv :b [:a 1 :b 11 :a 2 :b 22 :a 3 :b 33]) ; takes only 1 arg, not 3 args
=> [11 22 33]
The same rules hold for the inverse case. A map like :a 1 :b 2
is a function of 1 argument, so it can't be invoked with 3 args:
(apply :a 1, :b 2, :c 3 [:c :b :a]) ; 3 args to single-arg fn, so fails
but this works fine:
(mapv :a 1, :b 2, :c 3 [:c :b :a]) => [3 2 1]
apply
isn't a true special form, and maps aren't only unary functions; they can take a second arg for default value:(:foo 1 :bar 2) => 2
– Taylor Wood
Mar 23 at 12:39
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55301184%2fin-what-way-are-clojure-maps-functions%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Maps are functions of keys, as in your first two examples. Maps implement IFn
interface just like "regular" Clojure functions.
The reason apply
doesn't work in your examples is due to the "sequence" arguments being passed in the second position.
(apply #(:b %) :a 1 :b 2 :c 3)
In that example, the map argument is being turned into a sequence of key/value vectors/tuples, so they can be applied to #(:b %)
(which wouldn't work anyway because that anonymous function only takes one argument). This is how the map would look as it's being turned into a sequence and applied as arguments to the function:
user=> (seq :a 1 :b 2 :c 3)
([:a 1] [:b 2] [:c 3])
This second example doesn't work because :b
is not a sequence — it's a single keyword. This works though:
user=> (apply :a 1 :b 2 :c 3 [:b])
2
Note that calling a map-as-function with apply
and a sequence of keywords doesn't really make practical sense though.
add a comment |
Maps are functions of keys, as in your first two examples. Maps implement IFn
interface just like "regular" Clojure functions.
The reason apply
doesn't work in your examples is due to the "sequence" arguments being passed in the second position.
(apply #(:b %) :a 1 :b 2 :c 3)
In that example, the map argument is being turned into a sequence of key/value vectors/tuples, so they can be applied to #(:b %)
(which wouldn't work anyway because that anonymous function only takes one argument). This is how the map would look as it's being turned into a sequence and applied as arguments to the function:
user=> (seq :a 1 :b 2 :c 3)
([:a 1] [:b 2] [:c 3])
This second example doesn't work because :b
is not a sequence — it's a single keyword. This works though:
user=> (apply :a 1 :b 2 :c 3 [:b])
2
Note that calling a map-as-function with apply
and a sequence of keywords doesn't really make practical sense though.
add a comment |
Maps are functions of keys, as in your first two examples. Maps implement IFn
interface just like "regular" Clojure functions.
The reason apply
doesn't work in your examples is due to the "sequence" arguments being passed in the second position.
(apply #(:b %) :a 1 :b 2 :c 3)
In that example, the map argument is being turned into a sequence of key/value vectors/tuples, so they can be applied to #(:b %)
(which wouldn't work anyway because that anonymous function only takes one argument). This is how the map would look as it's being turned into a sequence and applied as arguments to the function:
user=> (seq :a 1 :b 2 :c 3)
([:a 1] [:b 2] [:c 3])
This second example doesn't work because :b
is not a sequence — it's a single keyword. This works though:
user=> (apply :a 1 :b 2 :c 3 [:b])
2
Note that calling a map-as-function with apply
and a sequence of keywords doesn't really make practical sense though.
Maps are functions of keys, as in your first two examples. Maps implement IFn
interface just like "regular" Clojure functions.
The reason apply
doesn't work in your examples is due to the "sequence" arguments being passed in the second position.
(apply #(:b %) :a 1 :b 2 :c 3)
In that example, the map argument is being turned into a sequence of key/value vectors/tuples, so they can be applied to #(:b %)
(which wouldn't work anyway because that anonymous function only takes one argument). This is how the map would look as it's being turned into a sequence and applied as arguments to the function:
user=> (seq :a 1 :b 2 :c 3)
([:a 1] [:b 2] [:c 3])
This second example doesn't work because :b
is not a sequence — it's a single keyword. This works though:
user=> (apply :a 1 :b 2 :c 3 [:b])
2
Note that calling a map-as-function with apply
and a sequence of keywords doesn't really make practical sense though.
answered Mar 22 at 14:24
Taylor WoodTaylor Wood
12.1k1825
12.1k1825
add a comment |
add a comment |
A mathematical function is a set of ordered pairs such that there are no distinct pairs with the same first element. A mathematical function so defined takes only one argument.
Clojure maps are self-evidently mathematical functions, since the there are no distinct key-value pairs with the same key. Moreover, Clojure maps have a finite domain (set of keys
) and range/co-domain (set of values
).
As @TaylorWood has stated, Clojure maps are Clojure functions because they implement clojure.lang.IFn. They do so as operators yielding the value for a given key, so consistent with their interpretation as mathematical functions.
Your apply
syntax is wrong. You can write
user=> (apply :a 1, :b 2 [:a])
1
or
user=> (apply :a 1, :b 2 :a [])
1
You can supply some of the arguments for the function (the first argument to apply
) inline. The remainder comprise the sequence that is the last argument to apply
. Since there is exactly one argument here, we can put it inline or alone in the terminal sequence.
Similar considerations apply to the use of keywords as arguments.
Reply to @AlanThompson's comments
I've listened to and read Rich's talk that the question refers to. My definition of a function agrees with his.
My statement that "A mathematical function so defined takes only one argument" is self evidently correct.
You could contend that my definition isn't the conventional one. But even that is false. If you read the Multivariate_function part of the Wikipedia article we both refer to, you will find
More formally, a function of n variables is a function whose domain is
a set of n-tuples
...
When using function notation, one usually omits the parentheses
surrounding tuples, writingf(x1 , x2)
instead off((x1 , x 2))
.
In other words, the idea that a (mathematical) function takes several arguments is a harmless informality that allows simpler notation.
Where does that leave programming languages? Most of them have functions of any arity: in Clojure's case, any finite set of arities, including an infinite one.
The simplest way to regard Clojure functions is that they take an inline sequence of arguments, perhaps an empty one. It would be possible to formulate mathematical functions in this way: mappings from sequences of things to things. But it just isn't done.
Many functions in math take more than 1 arg:z=2x+3y
being a simple example.
– Alan Thompson
Mar 22 at 17:27
@AlanThompson In that case, the first element in your order pair would simply be another ordered pair -- i.e., ((x,y), z)
– Nathan Davis
Mar 22 at 19:29
It is not that simple. 6 DOF models for aircraft, motorcycles, etc measure both position & rotation (x2) in 3D (x3), and may include derivatives 0, 1 and 2 (x3). That makes 18 input arguments to a function!
– Alan Thompson
Mar 22 at 20:24
@AlanThompson That is quite simple, mathematically. The function is a set of ordered pairs whose first element are 18-tuples. Unpleasant and offensive to you as a programmer, but nothing wrong with it in theory. All functions, of any number of arguments, can be viewed in this way.
– amalloy
Mar 23 at 0:32
I am simply trying to refute the incorrect statement, "A mathematical function so defined takes only one argument". This will mislead people. A generalized function takes N inputs and produces M outputs: en.wikipedia.org/wiki/Function_(mathematics)#Arrow_notation.
– Alan Thompson
Mar 23 at 3:28
add a comment |
A mathematical function is a set of ordered pairs such that there are no distinct pairs with the same first element. A mathematical function so defined takes only one argument.
Clojure maps are self-evidently mathematical functions, since the there are no distinct key-value pairs with the same key. Moreover, Clojure maps have a finite domain (set of keys
) and range/co-domain (set of values
).
As @TaylorWood has stated, Clojure maps are Clojure functions because they implement clojure.lang.IFn. They do so as operators yielding the value for a given key, so consistent with their interpretation as mathematical functions.
Your apply
syntax is wrong. You can write
user=> (apply :a 1, :b 2 [:a])
1
or
user=> (apply :a 1, :b 2 :a [])
1
You can supply some of the arguments for the function (the first argument to apply
) inline. The remainder comprise the sequence that is the last argument to apply
. Since there is exactly one argument here, we can put it inline or alone in the terminal sequence.
Similar considerations apply to the use of keywords as arguments.
Reply to @AlanThompson's comments
I've listened to and read Rich's talk that the question refers to. My definition of a function agrees with his.
My statement that "A mathematical function so defined takes only one argument" is self evidently correct.
You could contend that my definition isn't the conventional one. But even that is false. If you read the Multivariate_function part of the Wikipedia article we both refer to, you will find
More formally, a function of n variables is a function whose domain is
a set of n-tuples
...
When using function notation, one usually omits the parentheses
surrounding tuples, writingf(x1 , x2)
instead off((x1 , x 2))
.
In other words, the idea that a (mathematical) function takes several arguments is a harmless informality that allows simpler notation.
Where does that leave programming languages? Most of them have functions of any arity: in Clojure's case, any finite set of arities, including an infinite one.
The simplest way to regard Clojure functions is that they take an inline sequence of arguments, perhaps an empty one. It would be possible to formulate mathematical functions in this way: mappings from sequences of things to things. But it just isn't done.
Many functions in math take more than 1 arg:z=2x+3y
being a simple example.
– Alan Thompson
Mar 22 at 17:27
@AlanThompson In that case, the first element in your order pair would simply be another ordered pair -- i.e., ((x,y), z)
– Nathan Davis
Mar 22 at 19:29
It is not that simple. 6 DOF models for aircraft, motorcycles, etc measure both position & rotation (x2) in 3D (x3), and may include derivatives 0, 1 and 2 (x3). That makes 18 input arguments to a function!
– Alan Thompson
Mar 22 at 20:24
@AlanThompson That is quite simple, mathematically. The function is a set of ordered pairs whose first element are 18-tuples. Unpleasant and offensive to you as a programmer, but nothing wrong with it in theory. All functions, of any number of arguments, can be viewed in this way.
– amalloy
Mar 23 at 0:32
I am simply trying to refute the incorrect statement, "A mathematical function so defined takes only one argument". This will mislead people. A generalized function takes N inputs and produces M outputs: en.wikipedia.org/wiki/Function_(mathematics)#Arrow_notation.
– Alan Thompson
Mar 23 at 3:28
add a comment |
A mathematical function is a set of ordered pairs such that there are no distinct pairs with the same first element. A mathematical function so defined takes only one argument.
Clojure maps are self-evidently mathematical functions, since the there are no distinct key-value pairs with the same key. Moreover, Clojure maps have a finite domain (set of keys
) and range/co-domain (set of values
).
As @TaylorWood has stated, Clojure maps are Clojure functions because they implement clojure.lang.IFn. They do so as operators yielding the value for a given key, so consistent with their interpretation as mathematical functions.
Your apply
syntax is wrong. You can write
user=> (apply :a 1, :b 2 [:a])
1
or
user=> (apply :a 1, :b 2 :a [])
1
You can supply some of the arguments for the function (the first argument to apply
) inline. The remainder comprise the sequence that is the last argument to apply
. Since there is exactly one argument here, we can put it inline or alone in the terminal sequence.
Similar considerations apply to the use of keywords as arguments.
Reply to @AlanThompson's comments
I've listened to and read Rich's talk that the question refers to. My definition of a function agrees with his.
My statement that "A mathematical function so defined takes only one argument" is self evidently correct.
You could contend that my definition isn't the conventional one. But even that is false. If you read the Multivariate_function part of the Wikipedia article we both refer to, you will find
More formally, a function of n variables is a function whose domain is
a set of n-tuples
...
When using function notation, one usually omits the parentheses
surrounding tuples, writingf(x1 , x2)
instead off((x1 , x 2))
.
In other words, the idea that a (mathematical) function takes several arguments is a harmless informality that allows simpler notation.
Where does that leave programming languages? Most of them have functions of any arity: in Clojure's case, any finite set of arities, including an infinite one.
The simplest way to regard Clojure functions is that they take an inline sequence of arguments, perhaps an empty one. It would be possible to formulate mathematical functions in this way: mappings from sequences of things to things. But it just isn't done.
A mathematical function is a set of ordered pairs such that there are no distinct pairs with the same first element. A mathematical function so defined takes only one argument.
Clojure maps are self-evidently mathematical functions, since the there are no distinct key-value pairs with the same key. Moreover, Clojure maps have a finite domain (set of keys
) and range/co-domain (set of values
).
As @TaylorWood has stated, Clojure maps are Clojure functions because they implement clojure.lang.IFn. They do so as operators yielding the value for a given key, so consistent with their interpretation as mathematical functions.
Your apply
syntax is wrong. You can write
user=> (apply :a 1, :b 2 [:a])
1
or
user=> (apply :a 1, :b 2 :a [])
1
You can supply some of the arguments for the function (the first argument to apply
) inline. The remainder comprise the sequence that is the last argument to apply
. Since there is exactly one argument here, we can put it inline or alone in the terminal sequence.
Similar considerations apply to the use of keywords as arguments.
Reply to @AlanThompson's comments
I've listened to and read Rich's talk that the question refers to. My definition of a function agrees with his.
My statement that "A mathematical function so defined takes only one argument" is self evidently correct.
You could contend that my definition isn't the conventional one. But even that is false. If you read the Multivariate_function part of the Wikipedia article we both refer to, you will find
More formally, a function of n variables is a function whose domain is
a set of n-tuples
...
When using function notation, one usually omits the parentheses
surrounding tuples, writingf(x1 , x2)
instead off((x1 , x 2))
.
In other words, the idea that a (mathematical) function takes several arguments is a harmless informality that allows simpler notation.
Where does that leave programming languages? Most of them have functions of any arity: in Clojure's case, any finite set of arities, including an infinite one.
The simplest way to regard Clojure functions is that they take an inline sequence of arguments, perhaps an empty one. It would be possible to formulate mathematical functions in this way: mappings from sequences of things to things. But it just isn't done.
edited Mar 23 at 23:10
answered Mar 22 at 17:10
ThumbnailThumbnail
11.2k11628
11.2k11628
Many functions in math take more than 1 arg:z=2x+3y
being a simple example.
– Alan Thompson
Mar 22 at 17:27
@AlanThompson In that case, the first element in your order pair would simply be another ordered pair -- i.e., ((x,y), z)
– Nathan Davis
Mar 22 at 19:29
It is not that simple. 6 DOF models for aircraft, motorcycles, etc measure both position & rotation (x2) in 3D (x3), and may include derivatives 0, 1 and 2 (x3). That makes 18 input arguments to a function!
– Alan Thompson
Mar 22 at 20:24
@AlanThompson That is quite simple, mathematically. The function is a set of ordered pairs whose first element are 18-tuples. Unpleasant and offensive to you as a programmer, but nothing wrong with it in theory. All functions, of any number of arguments, can be viewed in this way.
– amalloy
Mar 23 at 0:32
I am simply trying to refute the incorrect statement, "A mathematical function so defined takes only one argument". This will mislead people. A generalized function takes N inputs and produces M outputs: en.wikipedia.org/wiki/Function_(mathematics)#Arrow_notation.
– Alan Thompson
Mar 23 at 3:28
add a comment |
Many functions in math take more than 1 arg:z=2x+3y
being a simple example.
– Alan Thompson
Mar 22 at 17:27
@AlanThompson In that case, the first element in your order pair would simply be another ordered pair -- i.e., ((x,y), z)
– Nathan Davis
Mar 22 at 19:29
It is not that simple. 6 DOF models for aircraft, motorcycles, etc measure both position & rotation (x2) in 3D (x3), and may include derivatives 0, 1 and 2 (x3). That makes 18 input arguments to a function!
– Alan Thompson
Mar 22 at 20:24
@AlanThompson That is quite simple, mathematically. The function is a set of ordered pairs whose first element are 18-tuples. Unpleasant and offensive to you as a programmer, but nothing wrong with it in theory. All functions, of any number of arguments, can be viewed in this way.
– amalloy
Mar 23 at 0:32
I am simply trying to refute the incorrect statement, "A mathematical function so defined takes only one argument". This will mislead people. A generalized function takes N inputs and produces M outputs: en.wikipedia.org/wiki/Function_(mathematics)#Arrow_notation.
– Alan Thompson
Mar 23 at 3:28
Many functions in math take more than 1 arg:
z=2x+3y
being a simple example.– Alan Thompson
Mar 22 at 17:27
Many functions in math take more than 1 arg:
z=2x+3y
being a simple example.– Alan Thompson
Mar 22 at 17:27
@AlanThompson In that case, the first element in your order pair would simply be another ordered pair -- i.e., ((x,y), z)
– Nathan Davis
Mar 22 at 19:29
@AlanThompson In that case, the first element in your order pair would simply be another ordered pair -- i.e., ((x,y), z)
– Nathan Davis
Mar 22 at 19:29
It is not that simple. 6 DOF models for aircraft, motorcycles, etc measure both position & rotation (x2) in 3D (x3), and may include derivatives 0, 1 and 2 (x3). That makes 18 input arguments to a function!
– Alan Thompson
Mar 22 at 20:24
It is not that simple. 6 DOF models for aircraft, motorcycles, etc measure both position & rotation (x2) in 3D (x3), and may include derivatives 0, 1 and 2 (x3). That makes 18 input arguments to a function!
– Alan Thompson
Mar 22 at 20:24
@AlanThompson That is quite simple, mathematically. The function is a set of ordered pairs whose first element are 18-tuples. Unpleasant and offensive to you as a programmer, but nothing wrong with it in theory. All functions, of any number of arguments, can be viewed in this way.
– amalloy
Mar 23 at 0:32
@AlanThompson That is quite simple, mathematically. The function is a set of ordered pairs whose first element are 18-tuples. Unpleasant and offensive to you as a programmer, but nothing wrong with it in theory. All functions, of any number of arguments, can be viewed in this way.
– amalloy
Mar 23 at 0:32
I am simply trying to refute the incorrect statement, "A mathematical function so defined takes only one argument". This will mislead people. A generalized function takes N inputs and produces M outputs: en.wikipedia.org/wiki/Function_(mathematics)#Arrow_notation.
– Alan Thompson
Mar 23 at 3:28
I am simply trying to refute the incorrect statement, "A mathematical function so defined takes only one argument". This will mislead people. A generalized function takes N inputs and produces M outputs: en.wikipedia.org/wiki/Function_(mathematics)#Arrow_notation.
– Alan Thompson
Mar 23 at 3:28
add a comment |
I'm not sure what the practical goal of this question is, but it is interesting from an academic point of view.
The keyword "function" :b
in the following is a function of 1 argument:
(:b :a 1 :b 2) => 2
It is like this function:
(defn get-b [m] (get m :b)) ; takes a single map arg
(get-b :a 3 :b 33) ; only 1 arg, so no problem
=> 33
The special form apply
re-writes the function call from having a single collection argument to having multiple, individual args. Comparing before & after we get:
(apply some-fn [1 2 3] ) ; using apply
(some-fn 1 2 3 ) ; without apply (note missing square brackets!)
So, apply
allows you to "spread" args from a collection as if you had typed them as separate, individual args in the function call. If your collection has only 1 element, using apply has little effect:
(apply :b [:a 3 :b 33] ) ; a collection of 1 element
(:b :a 3 :b 33 ) ; only 1 arg, so no problem
Because the function :b takes only 1 arg, the following won't work:
(apply #(:b %) [:a 1 :b 11 :a 2 :b 22 :a 3 :b 33]) ; takes only 1 arg, not 3 args
However, you can invoke the 1-arg function :b
multiple times using map
or mapv
:
(mapv :b [:a 1 :b 11 :a 2 :b 22 :a 3 :b 33]) ; takes only 1 arg, not 3 args
=> [11 22 33]
The same rules hold for the inverse case. A map like :a 1 :b 2
is a function of 1 argument, so it can't be invoked with 3 args:
(apply :a 1, :b 2, :c 3 [:c :b :a]) ; 3 args to single-arg fn, so fails
but this works fine:
(mapv :a 1, :b 2, :c 3 [:c :b :a]) => [3 2 1]
apply
isn't a true special form, and maps aren't only unary functions; they can take a second arg for default value:(:foo 1 :bar 2) => 2
– Taylor Wood
Mar 23 at 12:39
add a comment |
I'm not sure what the practical goal of this question is, but it is interesting from an academic point of view.
The keyword "function" :b
in the following is a function of 1 argument:
(:b :a 1 :b 2) => 2
It is like this function:
(defn get-b [m] (get m :b)) ; takes a single map arg
(get-b :a 3 :b 33) ; only 1 arg, so no problem
=> 33
The special form apply
re-writes the function call from having a single collection argument to having multiple, individual args. Comparing before & after we get:
(apply some-fn [1 2 3] ) ; using apply
(some-fn 1 2 3 ) ; without apply (note missing square brackets!)
So, apply
allows you to "spread" args from a collection as if you had typed them as separate, individual args in the function call. If your collection has only 1 element, using apply has little effect:
(apply :b [:a 3 :b 33] ) ; a collection of 1 element
(:b :a 3 :b 33 ) ; only 1 arg, so no problem
Because the function :b takes only 1 arg, the following won't work:
(apply #(:b %) [:a 1 :b 11 :a 2 :b 22 :a 3 :b 33]) ; takes only 1 arg, not 3 args
However, you can invoke the 1-arg function :b
multiple times using map
or mapv
:
(mapv :b [:a 1 :b 11 :a 2 :b 22 :a 3 :b 33]) ; takes only 1 arg, not 3 args
=> [11 22 33]
The same rules hold for the inverse case. A map like :a 1 :b 2
is a function of 1 argument, so it can't be invoked with 3 args:
(apply :a 1, :b 2, :c 3 [:c :b :a]) ; 3 args to single-arg fn, so fails
but this works fine:
(mapv :a 1, :b 2, :c 3 [:c :b :a]) => [3 2 1]
apply
isn't a true special form, and maps aren't only unary functions; they can take a second arg for default value:(:foo 1 :bar 2) => 2
– Taylor Wood
Mar 23 at 12:39
add a comment |
I'm not sure what the practical goal of this question is, but it is interesting from an academic point of view.
The keyword "function" :b
in the following is a function of 1 argument:
(:b :a 1 :b 2) => 2
It is like this function:
(defn get-b [m] (get m :b)) ; takes a single map arg
(get-b :a 3 :b 33) ; only 1 arg, so no problem
=> 33
The special form apply
re-writes the function call from having a single collection argument to having multiple, individual args. Comparing before & after we get:
(apply some-fn [1 2 3] ) ; using apply
(some-fn 1 2 3 ) ; without apply (note missing square brackets!)
So, apply
allows you to "spread" args from a collection as if you had typed them as separate, individual args in the function call. If your collection has only 1 element, using apply has little effect:
(apply :b [:a 3 :b 33] ) ; a collection of 1 element
(:b :a 3 :b 33 ) ; only 1 arg, so no problem
Because the function :b takes only 1 arg, the following won't work:
(apply #(:b %) [:a 1 :b 11 :a 2 :b 22 :a 3 :b 33]) ; takes only 1 arg, not 3 args
However, you can invoke the 1-arg function :b
multiple times using map
or mapv
:
(mapv :b [:a 1 :b 11 :a 2 :b 22 :a 3 :b 33]) ; takes only 1 arg, not 3 args
=> [11 22 33]
The same rules hold for the inverse case. A map like :a 1 :b 2
is a function of 1 argument, so it can't be invoked with 3 args:
(apply :a 1, :b 2, :c 3 [:c :b :a]) ; 3 args to single-arg fn, so fails
but this works fine:
(mapv :a 1, :b 2, :c 3 [:c :b :a]) => [3 2 1]
I'm not sure what the practical goal of this question is, but it is interesting from an academic point of view.
The keyword "function" :b
in the following is a function of 1 argument:
(:b :a 1 :b 2) => 2
It is like this function:
(defn get-b [m] (get m :b)) ; takes a single map arg
(get-b :a 3 :b 33) ; only 1 arg, so no problem
=> 33
The special form apply
re-writes the function call from having a single collection argument to having multiple, individual args. Comparing before & after we get:
(apply some-fn [1 2 3] ) ; using apply
(some-fn 1 2 3 ) ; without apply (note missing square brackets!)
So, apply
allows you to "spread" args from a collection as if you had typed them as separate, individual args in the function call. If your collection has only 1 element, using apply has little effect:
(apply :b [:a 3 :b 33] ) ; a collection of 1 element
(:b :a 3 :b 33 ) ; only 1 arg, so no problem
Because the function :b takes only 1 arg, the following won't work:
(apply #(:b %) [:a 1 :b 11 :a 2 :b 22 :a 3 :b 33]) ; takes only 1 arg, not 3 args
However, you can invoke the 1-arg function :b
multiple times using map
or mapv
:
(mapv :b [:a 1 :b 11 :a 2 :b 22 :a 3 :b 33]) ; takes only 1 arg, not 3 args
=> [11 22 33]
The same rules hold for the inverse case. A map like :a 1 :b 2
is a function of 1 argument, so it can't be invoked with 3 args:
(apply :a 1, :b 2, :c 3 [:c :b :a]) ; 3 args to single-arg fn, so fails
but this works fine:
(mapv :a 1, :b 2, :c 3 [:c :b :a]) => [3 2 1]
edited Mar 22 at 18:14
answered Mar 22 at 15:12
Alan ThompsonAlan Thompson
14.7k22535
14.7k22535
apply
isn't a true special form, and maps aren't only unary functions; they can take a second arg for default value:(:foo 1 :bar 2) => 2
– Taylor Wood
Mar 23 at 12:39
add a comment |
apply
isn't a true special form, and maps aren't only unary functions; they can take a second arg for default value:(:foo 1 :bar 2) => 2
– Taylor Wood
Mar 23 at 12:39
apply
isn't a true special form, and maps aren't only unary functions; they can take a second arg for default value: (:foo 1 :bar 2) => 2
– Taylor Wood
Mar 23 at 12:39
apply
isn't a true special form, and maps aren't only unary functions; they can take a second arg for default value: (:foo 1 :bar 2) => 2
– Taylor Wood
Mar 23 at 12:39
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55301184%2fin-what-way-are-clojure-maps-functions%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
If you use
(apply #((fn [x] x) %) :b)
or(apply #(:b %) (fn [x] x))
to substitute an explicit 1-arity function in the places where you're currently passing maps, you get the same errors -- demonstrating that the problem is not about maps' function-ness, but about the usage patterns themselves.– Charles Duffy
Mar 22 at 15:22