Apply Jade's feedback

Signed-off-by: Danila Fedorin <daniel.fedorin@hpe.com>
This commit is contained in:
Danila Fedorin 2025-10-09 17:34:46 -07:00
parent 0c4129337a
commit 86f1ba686a

View File

@ -80,7 +80,7 @@ I can think of another language that has pure functions...
# Programming in Haskell # Programming in Haskell
Without mutability and loops, Haskell programmers use pattern-matching and recursion to express their algorithms. Without mutability and loops, (purely) functional programmers use pattern-matching and recursion to express their algorithms.
* Data structures are defined by enumerating their possible cases. A list is either empty, or a head element followed by a tail list. * Data structures are defined by enumerating their possible cases. A list is either empty, or a head element followed by a tail list.
@ -481,7 +481,7 @@ record _cons {
# Extracting Types from Format Strings # Extracting Types from Format Strings
```Chapel ```Chapel
proc specifiers(param s: string, param i: int) type { proc specifiers(param s: string, param i: int = 0) type {
if i >= s.size then return _nil; if i >= s.size then return _nil;
if s[i] == "%" { if s[i] == "%" {
@ -509,7 +509,7 @@ proc specifiers(param s: string, param i: int) type {
Let's give it a quick try: Let's give it a quick try:
```Chapel ```Chapel
writeln(specifiers("Hello, %s! Your ChapelCon submission is #%i\n", 0) : string); writeln(specifiers("Hello, %s! Your ChapelCon submission is #%i\n") : string);
``` ```
The above prints: The above prints:
@ -550,16 +550,16 @@ _cons(string,"a string",_cons(int(64),"a signed integer",_nil))
* To support the empty-specifier case (Chapel varargs don't allow zero arguments): * To support the empty-specifier case (Chapel varargs don't allow zero arguments):
```Chapel ```Chapel
proc fprintln(param format: string) where specifiers(format, 0).length == 0 { proc fprintln(param format: string) where specifiers(format).length == 0 {
writeln(format); writeln(format);
} }
``` ```
* If we do have type specifiers, to ensure our earlier assumption of `size` matching: * If we do have type specifiers, to ensure our earlier assumption of `size` matching:
```Chapel ```Chapel
proc fprintln(param format: string, args...) proc fprintln(param format: string, args...)
where specifiers(format, 0).length != args.size { where specifiers(format).length != args.size {
compilerError("'fprintln' with this format string expects " + compilerError("'fprintln' with this format string expects " +
specifiers(format, 0).length : string + specifiers(format).length : string +
" argument(s) but got " + args.size : string); " argument(s) but got " + args.size : string);
} }
``` ```
@ -572,7 +572,7 @@ _cons(string,"a string",_cons(int(64),"a signed integer",_nil))
```Chapel ```Chapel
proc fprintln(param format: string, args...) { proc fprintln(param format: string, args...) {
validate(specifiers(format, 0), args.type, 0); validate(specifiers(format), args.type, 0);
writef(format + "\n", (...args)); writef(format + "\n", (...args));
} }
@ -707,7 +707,7 @@ For any two types, the _disjoint union_ of these two types defines values that a
* We can build up more complex types by combining these two operations. * We can build up more complex types by combining these two operations.
* Need a triple of types $A$, $B$, and $C$? Use $A \times (B \times C)$. * Need a triple of types $A$, $B$, and $C$? Use $A \times (B \times C)$.
* Similarly, "any one of three types" can be expressed as $A + (B + C)$. * Similarly, "any one of three types" can be expressed as $A + (B + C)$.
* A `Result<T>` type (in Rust, or `optional<T>` in C++) is $T + \text{Unit}$. * A `Option<T>` type (in Rust, or `optional<T>` in C++) is $T + \text{Unit}$.
* `Unit` is a type with a single value (there's only one `None` / `std::nullopt`). * `Unit` is a type with a single value (there's only one `None` / `std::nullopt`).
* Notice that in Chapel, we moved up one level * Notice that in Chapel, we moved up one level
@ -745,7 +745,7 @@ For any two types, the _disjoint union_ of these two types defines values that a
</div> </div>
* So, we can't enforce that the user doesn't pass `int` to our `length` function defined on lists. * So, we can't enforce that the user doesn't pass `int` to our `length` function defined on lists.
* We also can't enforce that `InL` is instantiated with the right type. * We also can't enforce that `InL` is instantiated with the right type.
* So, we lose some safety compare to Haskell... * So, we lose some safety compared to Haskell...
* ...but we're getting the compiler to do arbitrary computations for us at compile-time. * ...but we're getting the compiler to do arbitrary computations for us at compile-time.
--- ---