I'm also curious about this func/proc distinction and have some questions. It certainly isn't a new concept. Functional languages like Haskell have a similar distinction between effectful actions and pure functions. D also has pure functions that can only call other pure functions, but I'm not sure how well that has worked out in practice. Languages like SML/OCaml make it easy to write purely functional code, but I don't think the language enforces it.
1:
Is there really no way to reuse procedural code in a pure setting? Say I have a procedure
proc inPlaceSort(a: mutable IntArray) { ... }
Is there any way to use this proc to define a func that returns a sorted copy? For example:
Do I have to write two separate sorting algorithms? In Haskell I can implement both efficiently with a single implementation in the ST Monad.
2:
Can pure functions perform logging?
3:
Can a procedure declare some parameters as immutable or as output-only?
- Immutable parameters: often you will want to perform an effect with some context which you don't want to mutate. Const parameters are heavily used in C++ and Rust.
- Output parameters: these are parameters that are initialized by the callee and not the caller. Most languages don't need this as they can return one or more values instead, but C# is a language that has this specific feature.
4:
Why invent a new term "expressive conditional" when "conditional expression" already exists? :^)
1. You’re correct, there’s no way to do that. Fortunately in this case, you’d want to use the native sort function anyway because it’ll be much faster than one written in JS/Bagel, and that is accessible in a pure context (as a pure function of an array or iterator; not in-place). There will be some barriers to certain optimizations in Bagel, but that’s done knowingly. Bagel is intended as an application-level language, so certain choices are made that prioritize maintainability over performance. With that said, performance is still a priority, and certain things like the focus on iterators over array-cloning are there to tackle common JS performance problems.
2. I’m planning to make an exception here for debugging purposes; I’m thinking a function or operator that logs a value and then evaluates to it. Not strictly pure, but close enough from a maintainability standpoint.
3. Yes, any type can be labeled “const”, which is recursive. If a proc has a const argument, an otherwise-mutable object can be passed to it and it will just be treated as const within that proc. However, a const object cannot be passed to a non-const parameter (or variable, etc), otherwise some other code could then mutate it. Assignable (output) parameters will not be supported, but contents of parameters can be mutated by procs. I specifically wanted to discourage people from using procs to generate values; they should only say what to do with the values.
4. I may not have been fully versed on the terminology :)
1: Is there really no way to reuse procedural code in a pure setting? Say I have a procedure
Is there any way to use this proc to define a func that returns a sorted copy? For example: Do I have to write two separate sorting algorithms? In Haskell I can implement both efficiently with a single implementation in the ST Monad.2: Can pure functions perform logging?
3: Can a procedure declare some parameters as immutable or as output-only?
- Immutable parameters: often you will want to perform an effect with some context which you don't want to mutate. Const parameters are heavily used in C++ and Rust.
- Output parameters: these are parameters that are initialized by the callee and not the caller. Most languages don't need this as they can return one or more values instead, but C# is a language that has this specific feature.
4: Why invent a new term "expressive conditional" when "conditional expression" already exists? :^)