Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
A claim that I recall being repeated in the Clojure for Lisp Programmers videos is that a great weakness of the earlier Lisps, particularly Common Lisp, is that too much is married to the list structure of Lisps, particularly cons cells. You can find one occurrence of this claim just at the 25 minute mark in the linked video, but I'm sure that I can remember hearing it elsewhere in the series. Importantly, at that same point in the video, we see this slide, showing us that Clojure has many other data structures than just the old school Lispy lists:
This troubles me. My knowledge of Lisp is quite limited, but I've always been told that a key element of its legendary metaprogrmmability is that everything - yes, everything - is a list and that this is what prevents the sort of errors that we get when trying to metaprogram other languages. Does this suggest that by adding new first-class data structures, Clojure has reduces its homoiconicity, thus making it more difficult to metaprogram than other Lisps, such as Common Lisp?
is that everything - yes, everything - is a list
that has never been true for Lisp
CL-USER 1 > (defun what-is-it? (thing)
(format t "~%~s is of type ~a.~%" thing (type-of thing))
(format t "It is ~:[not ~;~]a list.~%" (listp thing))
(values))
WHAT-IS-IT?
CL-USER 2 > (what-is-it? "hello world")
"hello world" is of type SIMPLE-TEXT-STRING.
It is not a list.
CL-USER 3 > (what-is-it? #2a((0 1) (2 3)))
#2A((0 1) (2 3)) is of type (SIMPLE-ARRAY T (2 2)).
It is not a list.
CL-USER 4 > (defstruct foo bar baz)
FOO
CL-USER 5 > (what-is-it? #S(foo :bar oops :baz zoom))
#S(FOO :BAR OOPS :BAZ ZOOM) is of type FOO.
It is not a list.
CL-USER 6 > (what-is-it? 23749287349723/840283423)
23749287349723/840283423 is of type RATIO.
It is not a list.
and because Lisp is a programmable programming language, we can add external representations for non-list data types:
Add a primitive notation for a FRAME class.
CL-USER 10 > (defclass frame () (slots))
#<STANDARD-CLASS FRAME 4210359BEB>
The printer:
CL-USER 11 > (defmethod print-object ((o frame) stream)
(format stream "[~{~A~^ ~}]"
(when (and (slot-boundp o 'slots)
(slot-value o 'slots))
(slot-value o 'slots))))
#<STANDARD-METHOD PRINT-OBJECT NIL (FRAME T) 40200011C3>
The reader:
CL-USER 12 > (set-macro-character
#\[
(lambda (stream char)
(let ((slots (read-delimited-list #\] stream))
(o (make-instance 'frame)))
(when slots
(setf (slot-value o 'slots) slots))
o)))
T
CL-USER 13 > (set-syntax-from-char #\] #\))
T
Now we can read/print these objects:
CL-USER 14 > [a b]
[A B]
CL-USER 15 > (what-is-it? [a b])
[A B] is of type FRAME.
It is not a list.
Let's break the word "homoiconicity" apart.
homo-, meaning "same"
iconic, here meaning something like "represented by"
-ity, meaning "something having such a property"
The quality that makes macros possible (or at least much easier) is that the language itself is represented with the same data structures that you use to represent other objects. Note that the word is not "monolistism", or "everything is a list". Since Clojure uses the same data structures to describe its syntax as it does to describe other values at runtime, there's no excuse to claim it is not homoiconic.
Funnily enough, I might say that one of the ways that Clojure is least homoiconic is a feature that it actually shares with older lisps: it uses symbols to represent source code. In other lisps, this is very natural, because symbols are used for lots of other things. Clojure has keywords, though, which are used much more often to give names to data at runtime. Symbols are quite rarely used; I would go so far as to say that their primary usage is for representing source code elements! But all of the other features Clojure uses to represent source code elements are frequently used to represent other things as well: sequences, vectors, maps, strings, numbers, keywords, occasionally sets, and probably some other niche stuff I'm not thinking of now.
In Clojure, the only one of those extra data structures that is required for some language constructs, besides lists, are vectors, and those are in well-known places such as around sequences of arguments to a function, or in symbol/expression pairs of a let. All of them can be used for data literals, but data literals are less often something you want to involve when writing a Clojure macro, as compared to function calls and macro invocations, which are always in lists.
I am not aware of anything in Clojure that makes writing macros more difficult than in Common Lisp, and there are a few features there distinct to Clojure that can make it a little bit easier, such as the behavior where Clojure backquoted expressions by default will namespace-qualify symbols, which is often what you want to prevent 'capturing' a name accidentally.
As previous answerers pointed out, "homoiconicity" means nothing else than that the famous "code is data": That the code of a programming language consists 100% of data structures of that language, thus is easily build-able and manipulateable with the functions in the language usually used to manipulate the data structures.
Since Clojure data structures include lists, vectors, maps ... (those you listed) and since Clojure code is made of lists, vectors, maps ... Clojure code is homoiconic.
The same is true for Common Lisp and other lisps.
Common Lisp contains also lists, vectors, hash-tables etc. .
However, the code of Common Lisp sticks more rigidly to lists than Clojure does (function arguments are in a argument list and not in a vector like in Clojure).
So you can more consistently use functions to manipulate lists for metaprogramming purposes (macros).
Whether this is "more" homoiconic than Clojure is a philosophical question.
But definitely you need a smaller set of functions for manipulation of the code than in Clojure.
This question already has answers here:
Clojure get nested map value
(4 answers)
Closed 3 years ago.
I have a map
{
:key1 {
:key2 value
}
}
And I have list of keys say
[:key1, :key2]
I want to recursively call get function on the map for each element in the list and each sucessive call should use result from the previous funciton call.
I tried writing it using for, iterate and reduce-kv functions of clojure but I am not able to achieve.
Any hints or suggestions will be helpful.
Thank you in advance.
I could able to achieve it using get-in defined in clojure core - https://clojuredocs.org/clojure.core/get-in
(get-in map [:key1 :key2])
This question already has answers here:
How many arguments does an anonymous function expect in clojure?
(3 answers)
Closed 5 years ago.
I'm very new to Clojure and asking myself, how the arity of an anonymous function is defined/deducted.
Please consider the following poor-man count function:
(reduce #(+ 1 %1) 0 '(1 2 3 55))
Running it with clojure I'm getting the following error message:
ArityException Wrong number of args (2) passed to: user/eval1157/fn--1158 clojure.lang.AFn.throwArity (AFn.java:429)
However, it works fine with JavaScript-Clojure and returns 4 as desired (you can execute the command here).
Changing the command by exchanging %1->%2 to
(reduce #(+ 1 %2) 0 '(1 2 3 55))
would compile on both versions (but no longer work as count). In this case seemingly, it can be deduced from %2 that there are at least two arguments.
So which version of Clojure is right? Am I allowed to feed an arbitrary amount of arguments to an anonymous function defined via #(...) or only as many as mentioned inside of this function?
Should it be considered a bug in JavaScript-Clojure?
Edit: As have been explained in comments and in answer, that this is just the way how JavaScript works. There are differences to Java-Clojure, which are documented here, in particular:
There is currently no runtime enforcement of arity when calling a fn
The parameters in the resulting function is determined by the highest numbered used parameter. Thus by using %2 both become a 2 arity function, but since you only use %1 (or %) it becomes a one arity function in both versions of Clojure.
In JavaScript you can pass as many arguments as you'd like and even pass fewer than the parameter list. Variables without matching argument become undefined and arguments without defined parameters are simply not bound and available in the function. ClojureScript would have to add argument checking in each function in order to get the same behavior as in Clojure. It would be a bug if this is the specified behavior. Many transpiled languages does this.
The solution for your example is to not use the short version but rather fn:
(reduce (fn [a _] (+ 1 a)) 0 '(1 2 3 55))
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am trying to make a score function using lisp. The idea is that I have a list as input. This list must be sorted and each value should get a mark (the firest one has the highest mark)
I tried something like the normal sort, but i need to use the lambda operator
But my lisp is pretty bad .
An example to make it clear:
((o1 10 15 20) (o2 5 14 20) (o3 7 8 8)
output>
((o1 1 1 1) (o2 3 2 1) (o3 2 3 3))
it sorts the firest value from o1 with first from o2 and first from o3 and it ranks them .
I actually can't understand your question. But if the question is: "Help me to sort a list in common lisp" then:
1) `(setq o1 (20 30 15)) is a valid lisp expression and (20 30 15) is a list, but it is not quoted, so the interpreter will try to evaluate expression. And the rule of evaluation is "First element in expression is a function" so interpreter will try to evaluate a function that has a name "20" and will fail. You should write this:
(setq o1 '(20 30 15))
1') Usually it is better to use setf instead of setq (especially if you don't want to know the difference). And also it's better to define variable before setting a value to it. So it's better to write something like this:
(defparameter o1 '()) ;creating o1 with empty list
(setf o1 '(20 30 15))
1'') You should name you variables and function with understandable names. And if it is a global variable mark it with asterisks. For example
(defparameter *students-scores* '())
(setf *students-scores* '(20 30 15))
2) In common lisp list is a built in function that creates a list from it's arguments. Even if you are in your own package at the time this code will be executed (the default package is locked so you won't be able to redefine list function there), it is quite strange to redefine such function as list, so choose another name for your function
(defun sort-integer-list (lst)
(sort lst #'<))
3) You have parentheses mismatch in you code.
This question already has answers here:
Clojure syntax question re: #^
(2 answers)
Closed 9 years ago.
I have looked through Clojure documentation and at source code, however I cannot find the meaning of #^.
What does #^ do in the following, and where is it documented?
(defn- parse-headers [#^HttpResponse http-resp]
(into {} (map (fn [#^Header h] [(.toLowerCase (.getName h)) (.getValue h)])
(iterator-seq (.headerIterator http-resp)))))
It's just supposed to be a type hint, which is usually signified by ^TypeName before the parameter name in a function's parameter list. I'm not sure what the difference is between ^ and #^; maybe it's older syntax?