Last active
September 7, 2024 12:48
-
-
Save jbunke/60d7b7ba9779f8a44e96f2735ddd460e to your computer and use it in GitHub Desktop.
Simple prime number checker script in DeltaScript that showcases new language features: `when` statement and lambda expressions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Ignore .js file extension - only used so GitHub's JavaScript linter provides decent code highlighting | |
/* | |
This script accepts an integer `to_check` and returns true if and only if it is a prime number. | |
Note the use of a when statement, DeltaScript's answer to switch statements. | |
Cases in when statements take three forms: | |
1. `is` cases compare the control expression against an expression and execute their body if the values are equal | |
2. `passes` cases provide a predicate that the control expression is tested against. | |
For a control variable of type T, predicates are functions of type (T -> bool). | |
Predicates can be expressed as function pointers - ::function_name - or as lambda expressions | |
3. when statements can optionally include a final `otherwise` case, which is a universally true case that always | |
executes its body when reached. | |
Cases in when statements are checked sequentially as written. The control flow drops out of the statement once the body | |
of the first valid case has been executed. | |
*/ | |
(int to_check -> bool) { | |
when (to_check) { | |
// predicate is a lambda expression | |
passes n -> n <= 0 -> { | |
print("Please provide a POSITIVE integer"); | |
return false; | |
} | |
// equivalent to `else if (to_check == 1)` | |
is 1 -> return false; | |
// predicate is a function pointer | |
passes ::even -> return to_check == 2; | |
otherwise -> { | |
int factors = factors(to_check); | |
// #| is the length operator - can be called on collections (lists <>, arrays [], sets {}) and strings | |
bool prime = #|factors == 2; | |
if (!prime) { | |
string assembled = ""; | |
// type declarations in foreach loops are optional, as element type can be inferred from the iterable | |
for (factor in factors) | |
assembled += (assembled == "" ? "" : ", ") + factor; | |
print("[ " + assembled + " ]"); | |
} | |
return prime; | |
} | |
} | |
} | |
even(int n -> bool) -> n % 2 == 0 | |
factors(int n -> int<>) { | |
// Declares an immutable list of integers `factors` and initializes it to an empty list of integers | |
// immutability (`~` or `final`) means that `factors` cannot be reassigned; however the existing list may be modified | |
~ int<> factors = <>; | |
int sq = 1; | |
while (sq * sq < n) | |
sq++; | |
for (int check = sq - (sq * sq == n ? 0 : 1); check > 0; check--) | |
if (n % check == 0) { | |
factors.add(check, 0); | |
// appends the complementary factor if it is != to factor `check` | |
if (n / check != check) | |
factors.add(n / check); | |
} | |
return factors; | |
} |
My main reason for preferring the when
statement is that to_check
is omitted from our conditions. All conditions are performing checks on the value of that variable, so it seems redundant to reference it repeatedly.
Let me know what you think of when
in DeltaScript! I'd be curious to know what you think of...
- the choice of keywords (
when
,is
,passes
,otherwise
) - for example, I opted not to reuseelse
forotherwise
- the syntax generally
- the grammar
Links:
- DeltaScript repo
- Language implementation - (in active development and prone to breaking changes)
- A project that implements DeltaScript + source
Script boiled down to core logic:
(int to_check -> bool) {
when (to_check) {
passes n -> n <= 1 -> return false;
passes ::even -> return to_check == 2;
otherwise -> return #|factors(to_check) == 2;
}
}
even(int n -> bool) -> n % 2 == 0
factors(int n -> int<>) {
~ int<> factors = <>;
int sq = 1;
while (sq * sq < n)
sq++;
for (int check = sq - (sq * sq == n ? 0 : 1); check > 0; check--) {
if (n % check == 0) {
factors.add(check, 0);
if (n / check != check)
factors.add(n / check);
}
}
return factors;
}
Additional example
has_area(image img -> bool) -> img.w > 0 && img.h > 0
transparent_tl_pixel(image img -> bool) -> has_area(img) && img.pixel(0, 0).alpha == 0
// ...
tl_pixel_or_bw(image img -> color) {
when (img) {
passes ::transparent_tl_pixel -> return #000000;
passes ::has_area -> return img.pixel(0, 0);
otherwise -> return #ffffff;
}
}
// Yes, DeltaScript supports color hex code literals!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Comparison
Minimal representation of prime determination logic using different control flow statements
1. As
when
2. As
if ... else
Note that the omission of curly braces here is simply a matter of code style and personal preference.
The third case could also be expressed as an
else
branch.when
expressionNext I'd like to implement a
when
expression to make something like this possible...