Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debate if we should add mutation to KCL #22

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions imperative.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Should KCL be imperative?

Currently KCl tries to keep all its variables immutable. Should we allow mutation?

## Why immutable

- Fewer chances of bugs when variables cannot be updated
- Encourages users to use higher-level constructs like patterns, that can be optimized in both KCL and the engine much more easily than a for loop.
- Easy to map a specific geometric feature (e.g. a 2D polygon) to its definition in the IDE because a geometric feature is created once and then never changed, so it's fully defined at its source range. If geometry could be updated, we'd need the IDE to show where it was defined AND where the relevant change was made.
- KCL is about defining geometry, not about modeling a changing system. Mutation doesn't seem necessary.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add that it makes a lot of analyses (e.g., for the IDE), optimisations, and other reasoning about the code, much, much easier. In particular, partial execution (for sketch mode) and code mods will be much harder to get right in the presence of mutation

## Why mutation

- Mechanical engineers (MEs) will be coming from Python or JS. They will be used to imperative programming with loops and variables. The functional programming patterns (e.g. map and reduce) they'll need to engage with will be unfamiliar.
- Given that we're already asking MEs to go outside their comfort zone (by coding rather than using the GUI), we should make the language as intuitive as possible. This probably means for loops.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #15 for a proposal for a 'for loop' construct which subsumes for_each, map, and reduce (in most cases) and works with immutability, and I believe is easy to teach to programmers coming from Python/JS (though the actual details of how it works are somewhat complex).

- To keep KCL performant will require implementing persistant data structures. For example, to keep KCL immutable, Array.push currently clones the array into a new variable, and appends to the cloned array. It'd be much faster to just mutate the array in-place, but that'd require mutation. There are alternative high-performance immutable data structures but we'd need to understand and implement them. Certainly doable, but less immediately simple than reusing Rust's mutable datatypes.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once KittyCAD/modeling-app#1130 is fixed, I don't think adopting persistent data structures would be hard at all. There are only a few things that interact with arrays. Literals, map, reduce, push, and get index [].

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that in practice this shouldn't be a problem if we encourage using constructs like patterns rather than arrays. For performance, most variables would only require reference counting, not full persistent data structures. The latter could be layered on top of Rust data structures fairly easy (note that you don't really want a persistent data structure, which is emulating mutability in an immutable world, you want the opposite which is emulating immutability in a mutable but monotonic world. This is pretty easy - just use a Rust array and a variable which points to an earlier version of the array is a copy-on-write slice reference of the correct length, similarly for other data structures).

- Currently the engine is mutable and KCL is not. This leads to mismatches like <https://github.com/kittycad/modeling-app/issues/2728> which will be complicated to solve if we keep the language immutable, and trivial if we allow mutation.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I commented here, I don't think it is that hard to fix (though certainly non-trivial to fix properly)

- Many math formulae that MEs will try to implement are easier as imperative algorithms (citation needed)

## Implementation problems
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fear that there would be a large knock-on effect of such a large change to the character of the language which would mean a lot of changes to existing and planned constructs, and std lib functions.


- Should we allow any immutable variables? E.g. a difference between `const` and `var`?
- Currently KCL doesn't require any variable declaration i.e. you can do `x = 2`. This is fine in an immutable language, but with mutation it means you can't tell if `x = 2` is reassigning `x` or creating a new variable named `x`. We should consider making `const` and `var` keywords meaningful again, so it's clear if you're creating a new variable or not (and whether it is mutable).