# Insert!, cross-module struct mutation and symbol reference

**URL:** https://discourse.julialang.org/t/insert-cross-module-struct-mutation-and-symbol-reference/58707
**Category:** General Usage
**Created:** [April 6, 2021, 6:23pm UTC](https://discourse.julialang.org/t/insert-cross-module-struct-mutation-and-symbol-reference/58707 "2021-04-06T18:23:40Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Mark\_Nahabedian](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mark_nahabedian/32/16562_2.png) [@Mark\_Nahabedian](https://discourse.julialang.org/u/Mark_Nahabedian)
#### Post date: [April 6, 2021, 6:23pm UTC](https://discourse.julialang.org/t/insert-cross-module-struct-mutation-and-symbol-reference/58707/1 "2021-04-06T18:23:40Z")

</div>

Barkground:

The lecture notes for an open courseware class I’m working through uses an interactive Pluto notebook. I wanted to add an empty cell to my local copy of this notebook to work on one of the programming exrcises, but the keyboard gesture for doing that wasn’t working for me (in Google Chrome).

My question isn’t about the Pluto UI though. I saw the structure of the notebook file and decided it would be easy enough to write a command line tool that would add a cell to the notebook so long as the notebook wasn’t currently being served. Before diving in to doing uninforned file manipulation, I looked through Pluto.jl and found it was easy to identify a set of functions my program could call into to open and manipulate the notebook.

My Problem:

The present state of my effort is on GitHub:

[GitHub - MarkNahabedian/PlutoTool.jl: A command line utility for doiing simple manipulations on Pluto notebook files.](https://github.com/MarkNahabedian/PlutoTool.jl)

Im using insert! to insert a new Pluto.Cell into the Pluto.Notebook’s cells vector. I don’t understand why this isn’t working in my application but does work in some stripped down test cases.

My problem is that the length assertion is failing:

“”" new\_cell before/after notebook\_path relative\_to\_cell\_id  
Insert a new, enpty cell before or after the cell specified by existing\_cell\_id.  
The id of the new cell is returned.  
“”"  
function new\_cell(ctx::Context, before\_after::String, notebook\_path::String, relative\_to\_cell\_id::String)::String  
notebook = get\_notebook(notebook\_path)  
index = find\_cell(notebook, relative\_to\_cell\_id)  
rel = validate\_option(before\_after, :before, :after)  
@assert index \>= 1  
@assert index \<= length(notebook.cells)  
if rel == :after  
index = index + 1  
end  
cell = Pluto.Cell()  
len = length(notebook.cells)  
insert!(notebook.cells, index, cell)  
@assert length(notebook.cells) == len + 1  
Pluto.save\_notebook(notebook)  
@printf(ctx.stdout, “Inserted new cell %s\n”, string(cell.cell\_id))  
return string(cell.cell\_id)  
end

I’ve tried some stripped down examples, which both work:

As a lisp programmer I’ve learned that “modify in place” operations might need to relocate the object (in this case insert! aND THE Notebook’S vector of Cells), so one should assign the modified result back where it came from. I don’t seem to be able to write to notebook.cells though. If I do

notebook.cells = insert!(notebook.cells, index, cell)

I get the error " type Notebook has no field cells" which is somewhat misdirecting in that I was able to read the cells field without error, just bot set it. I remember reading someplace that Julia didn’t allow cross-module struct mutations.

I also tried using setfield!, but I don’t know how to refer to :cell from the Pluto module rather than my own.

I’ve tried searching the Pluto package for code that modifies Notebook.cells but didn’t find anything. It must be there someplace though otherwise how can people edit their notebooks.

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [April 6, 2021, 6:34pm UTC](https://discourse.julialang.org/t/insert-cross-module-struct-mutation-and-symbol-reference/58707/2 "2021-04-06T18:34:34Z")

</div>

> [@Mark\_Nahabedian](#):
>
> As a lisp programmer I’ve learned that “modify in place” operations might need to relocate the object (in this case insert! aND THE Notebook’S vector of Cells), so one should assign the modified result back where it came from.

That’s not necessary in Julia, at lest not in any circumstance I’ve come across.

> [@Mark\_Nahabedian](#):
>
> I remember reading someplace that Julia didn’t allow cross-module struct mutations.

Mm, no, that’s not a thing. There are no issues or restrictions on modifying `mutable structs`, regardless of what module your code or the definition is in.

> [@Mark\_Nahabedian](#):
>
> I don’t know how to refer to :cell from the Pluto module rather than my own.

Likewise, this is a red herring. The particular module in which the code lives is of no consequence.

> [@Mark\_Nahabedian](#):
>
> I get the error " type Notebook has no field cells" which is somewhat misdirecting in that I was able to read the cells field without error, just bot set it.

This is because the `.cells` accessor is actually provided by this `getproperty` definition:

> <https://github.com/fonsp/Pluto.jl/blob/2ebdaaf615c9491ba0b04271a9214665b5a3d5b5/src/notebook/Notebook.jl#L59-L71>

There’s no `setproperty!` implementation, presumably because Pluto.jl intentionally doesn’t support that particular way of modifying the cells.

That function also reveals why mutating `notebook.cells` doesn’t work. The `getproperty` method means that `notebook.cells` returns a _brand new_ vector (the output of `map`). You can mutate that all you want, but it has no effect on the notebook itself.

It looks like Pluto.jl doesn’t support what you’re trying to do, but it doesn’t look like it would be too hard to add it. As far as I can tell, it would require modifying both `notebook.cells_dict` and `notebook.cell_order`. That would probably best be done by adding a new `insert_cell!` function in Pluto.jl itself, but there’s no reason you can’t prototype that function in your own code (as you’re doing now).

---

<div class="post-metadata">

### Author: ![Mark\_Nahabedian](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mark_nahabedian/32/16562_2.png) [@Mark\_Nahabedian](https://discourse.julialang.org/u/Mark_Nahabedian)
#### Post date: [April 6, 2021, 7:25pm UTC](https://discourse.julialang.org/t/insert-cross-module-struct-mutation-and-symbol-reference/58707/3 "2021-04-06T19:25:24Z")

</div>

Thanks Robin. That makes things a lot clearer.

I’m hoping to not have to modify the Pluto package.

Now that you provided me with a much better understanding of what’s going on, I’ll try to push forward.

---

<div class="post-metadata">

### Author: ![Mark\_Nahabedian](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mark_nahabedian/32/16562_2.png) [@Mark\_Nahabedian](https://discourse.julialang.org/u/Mark_Nahabedian)
#### Post date: [April 6, 2021, 9:21pm UTC](https://discourse.julialang.org/t/insert-cross-module-struct-mutation-and-symbol-reference/58707/4 "2021-04-06T21:21:09Z")

</div>

Thanks again Robin.

This would have gone a lot more smoothly if the version of the Pluto sources I was looking at were the same version as julia was using. The old version is now wiped from my laptop.
