KittyCAD / modeling-app

The KittyCAD modeling app.
https://kittycad.io/modeling-app/download
MIT License
403 stars 35 forks source link

KCL: More flexible ranges #4275

Open adamchalmers opened 4 days ago

adamchalmers commented 4 days ago

Background

Right now, KCL ranges are always two (signed) integers, e.g. [-4..10]. Ranges always increment the start by 1 until it reaches the end.

Problem

We should support:

Descending iteration would simplify Nick B's involute gear example, which calculates the left edge from 0..10 and the right edge from 10..0

Solution

Allow ranges like [start:end:step] -- where step is a signed integer. If start > end then step must be negative, otherwise it'll be an error.

Other solutions or suggestions are very welcome!

lf94 commented 4 days ago

LGTM. Just wondering why not open it up to reals immediately

jtran commented 4 days ago
  1. In ML, you can write a pattern with a type in the middle of it to say that this part of the pattern has this type. I know we're far off from this, but it seems like the above syntax would conflict if we ever wanted to match on the start and end of a range and use : for type annotations. It's fine if the answer is, this is way too far off for us to care.
  2. Bike shed...

Second thing is mostly about style. I don't want this to block progress if everything else is figured out.

I never personally liked Python's [start:end:step] syntax. For one, the order differs from matlab and Julia, where the step is in the middle. So I end up always getting it wrong or having to look up the order. The notation has no inherent order that anyone would reasonably expect it to be in. [step:start:end] is equally valid.

The other thing is that if we intend to support unbounded ranges and slicing existing arrays one day, we end up with things like [0::2] or a[::-1]. I don't know what else to say other than I don't like it. Would this mean that :: syntax is off limits for other things too?

As for an alternative, in Ruby, you can say (10..0).step(-1). With just a few extra characters, it's clearer, in my opinion.

Since KCL doesn't have methods, I'm not sure what the equivalent would be. [10..0] |> step(-1)? Even if we got rid of %, it still doesn't roll off the tongue quite so nicely. But whatever it is, it needs to play well with our iteration story, and I'm not sure that's figured out. In CoffeeScript, for example, step isn't part of ranges. It's part of the looping syntax. It has an optional by -1.

lf94 commented 3 days ago

Really sorry for any hopes up; after reading Jon's comment it made me think about other aspects of this feature and I need to revoke the LGTM.

This proposal only covers a small slice of mathematical usage; specifically counting up and down monotonically. We need to support all kinds, such as by x^2, logn(x), even something crazy as sin(x) (which could produce an infinite loop or long list depending what kind of checking we do), etc.

Python or Haskell's list comprehensions / constructors are superior for this sort of thing. We really need to adopt those in some form. If this proposal can be shown to be extended to support this more powerful form of "list creation" then it's LGTM :p