clojure is supposed to be 'code is data' yet I can't add to the end of a list?

166 views
Skip to first unread message

SideStep

unread,
Jul 17, 2021, 8:24:02 AM7/17/21
to Clojure

I have a representation of a matrix in grid.clj file:

(-> (grid 10 10)
    (toggle 2 3 4 5)
    (off 2 3 4 5)
    (on 2 3 4 5))

It's a list of functionts, first one initializes a grid, others modify it.
Clojures' 'code is data' supposed to make it easy for me to modify that representation by adding an instrucion at the end of collection. List is an ordered collection right? Order matters. How do I add an instruction to the end of the list then?
Something like this:

(def grid (read-string (slurp "grid.clj")))
(conj grid '(off 1 2 3 6))

Yet I can't add to the end of the list, which is a data structure that is evaluatable as code. How is it 'code as data' if I can't add to the end of the ordered collection that is meant for code (as data)?

Tanya Moldovan

unread,
Jul 17, 2021, 3:21:29 PM7/17/21
to clo...@googlegroups.com

Hi,

conj adds at the end of a vector, but at the beginning of a list. It is how it is implemented. I think this and this sums it up why.

You could achieve what you want by using concat (note this returns a LazySeq):
user=> (concat grid '((off 1 2 3 6)))
(-> (grid 10 10) (toggle 2 3 4 5) (off 2 3 4 5) (on 2 3 4 5) (off 1 2 3 6))
Though I'm not exactly sure what is the end goal of this but I'd rethink the way it is done. 



--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/clojure/efd72013-a85e-46e8-b9db-10dde1a8a235n%40googlegroups.com.

SideStep

unread,
Jul 18, 2021, 12:40:44 PM7/18/21
to Clojure
Thanks Tania! The point I'm making is that list (data structure for evaluatable data/code) is not easily manipulatable with code in clojure. So much for 'code-is-data'...
Thanks for the suggestion.
In regards to rethinking it: it is supposed to be commands coming-in that sets parts of the grid with on/off/toggle... I want to append those commands (code) as data to the representation of a grid and evaluate the list of commands to get the final state of the grid.
Trying to embrace this code-is-data thing here.

James Reeves

unread,
Jul 18, 2021, 1:43:20 PM7/18/21
to 'EuAndreh' via Clojure
"Code is data" comes up in Clojure less than newcomers might expect. As a rule of thumb, it should be the last tool you reach for, as it's easier to work with data structures that have a simpler and more constrained syntax.

It's often hard to give good advice when context is lacking, but if you have a grid, and want to supply a sequence of instructions to modify it, and you want to inspect and manipulate those instructions, then I'd suggest something like:

    (transform
     (grid 10 10)
     [[:toggle 2 3 4 5]
      [:off 2 3 4 5]
      [:on 2 3 4 5]])

Joe R. Smith

unread,
Jul 18, 2021, 1:43:32 PM7/18/21
to clo...@googlegroups.com
It is a singly linked list, so the natural position at which to add is the front. conj will add to the front of lists and to the end of vectors.

Consider using a vector if you want to append to the end. It'd be more semantically correct.

More background: If you append to the end of a singly linked list, generally, you'd have to follow the references starting from the first element until you reached the last element. Clojure uses persistent data structures, meaning when you add an item to a collection you share structure with the original item. In the case of a singly linked list, adding an item to the front is as simple as creating a new list that points to the old list. E.g., adding 5 to the linked list 2 -> 3 -> 4 can be thought of as 5 -> 2 -> 3 -> 4.

---
Joe R. Smith
@solussd


On Jul 17, 2021, at 2:21 PM, Tanya Moldovan <tanya.m...@gmail.com> wrote:



SideStep

unread,
Jul 19, 2021, 9:00:09 AM7/19/21
to Clojure
Thanks James, will for something like it I think. Still, would be nice if code was manipulatable with ease - clojure style. Code-is-data such a powerful idea.

James Reeves

unread,
Jul 19, 2021, 9:28:32 AM7/19/21
to 'EuAndreh' via Clojure
Don't get be wrong: Clojure can manipulate lists easily. You can append items to a list with (concat xs '(5)) or use syntax quoting `(~@xs 5). You just can't use conj specifically, as that function has a particular use case.

The problem with manipulating code is that code is complex. The same functionality can be written in many different ways, and it's hard to account for every possibility, so any abstraction that treats code as data tends to be either be leaky or very simple (or occasionally, very complex).

Clojure can treat code as data, but it's one of those tools that has a narrow use case. Clojure's philosophy more revolves around replacing code with pure data, where possible. Reading is safer and more predictable than evaluating, and evaluating within narrow constraints is often better than reaching for the more general purpose eval.
Reply all
Reply to author
Forward
0 new messages