First of all, Merry Christmas, second of all - This week I rewrote the array and object index syntax, again (yes again). I also improved (I think) the way functions and loops are defined. I introduced three new built-in functions and added a license.
New and improved function and for loop notation
Due to outside feedback and my own thoughts on the previously employed
function
and for
loop parameter notation, I decided to switch from:
1(for (_ i) 5 (println i))
2(fun square (_ n) (* n n))
To:
1(for [i] 5 (println i))
2(fun square [n] (* n n))
Reworked Array and Object indexing (V3)
Due to the aforementioned changes the currently not context aware parser
required a change for object and array indexing, this means prefixing the index
syntax with #
:
1(let person { array: [1 2 3] })
2(println person#["array"][0])
New built-in functions
This week I introduced some eagerly awaited built-in functions, such as mapping, filtering and asserting.
Map
This built-in allows for applying a function to every element of an array and returning a new array containing the result of each function application.
1(fun square [n] (* n n))
2(map (square) [1 2 3 4 5])
3;; [1 4 9 16 25]
Filter
The filter
built-in applies the function to every item in the array and keeps
the element in the resulting array if the function returns true, otherwise the
element is skipped in the result.
1(fun isEven [num] (= 0 (% num 2)))
2(filter (isEven) [1 2 3 4 5])
3;; [2 4]
Assert
Asserting makes sure state is correct in the program with a fast way for feedback:
1(assert (= 2 2))
assert
checks if the argument expression evaluates to true, otherwise it
panics. The built-in also panics when provided with more than one argument or
the argument evaluating to a non boolean value.
Finally, a License
I plan on implementing the embedding of sophia scripts into fully featured go application to improve the way these applications can be configured and scripted. I chose the permissive MIT license, due to me wanting to pave the way for almost all projects to use sophia if they desire to do so.
Planned features
Thinking about lambdas
Both map
and filter
require a previously defined function to apply to array
elements. This can be cumbersome and verbose to type, thus I thought a lot
about a clean and concise syntax approach to anonymous functions, specifically
for usage in the map
and filter
built-ins:
1(map (lambda [n] (* n n)) [1 2 3 4 5])
2(filter (lambda [n] (= 0 (% n 2))) [1 2 3 4 5])
This notation allows for omitting the function definition.
Array ranges
A previously very badly implemented feature was ranges for array creation, such as:
1(let zeroToThree [0..3]) ;; [0 1 2 3]
2(let oneToThree [1..3]) ;; [1 2 3]
I plan to reimplement this in a clean and efficient way.
Deconstructing objects
The last feature I thought about was deconstructing values from objects into variables:
1(let person { name: "anon" age: 25 })
2(let [name age] person)
3(let [name] person)
4;; shorthand for
5(let name person#["name"])
6(let age person#["age"])
7(let name person#["name"])