Old, Discarded Ideas
For several topics there are alternative ideas, that were discarded but are still worth mentioning.
Trailing Semicolons
- We could keep the trailing semicolons for now.
- Disadvantages of not having trailing semicolons:
- Errors are less easily recognized. (Walter Bright / D: „Redundancy helps“)
- Probably a completely new parser must be written, as the one from clang (for C++) no longer fits at all.
- Implicitly/clever multiline expressions as in Swift, Kotlin and JavaScript?
(Actually I don’t know / remember the rules anymore.)
Better Readable Keywords
- Instead of
class ... : ...Cilia could haveclass ... extends ...- good for extending base classes
class ... implements ...- good fit for implementing pure abstract base classes (like interfaces)
- But then we would have two different keywords. And what about mixed cases, i.e. abstract classes with partly function implementation? (Probably best to use
implementsthen, but still not nice.)
Basic / Arithmetic Types
Floatcould be 32-bit float:Float==Float32,- like in C++.
- Then
Float==Float32on all platforms.
Variable Declaration
- Very short variable declaration:
- Maybe possible to simply write
i = 3? - Maybe
i := 3?
- Maybe possible to simply write
let i = 0instead ofconst i = 0- similar to Swift and Carbon.
- In Rust
let mutis used for variables, - in JavaScript
letandconstare very similar with slight differences.
- Always starting with keyword
var- Examples:
var Int ivar i : Int
- In case
funcfor function declaration, but notvarfor variable declaration, is still not clear enough. - Swift, Kotlin and Circle always start variable declarations with
var. - Not starting with
varcould be especially problematic in connection with omitting the trailing semicolons.
- Examples:
Bitfields
One could define the order of bits in a bitfield.
- MSB (Most Significant Bit) first.
- This way you can use
class Float32Equivalent { UInt32:1 signIsNegative UInt32:8 exponent UInt32:23 significand // AKA mantissa }to read/interpret
Float32, - and with
class SignBitOfInt64 { UInt64:1 signIsNegative }signIsNegative is true for negative Int64.
- Bits are left-aligned, so the first element always covers the most-significant bit:
class MostSignificantThreeBits { UInt8:1 bit7 UInt8:1 bit6 UInt8:1 bit5 // ... } - This is what typical “MSB-first” C++ compilers do (on big-endian PowerPC, MIPS, SPARC).
- CiliaC may have to reverse the order of bit field elements and add some padding
UInt32:... __filler_for_right_alignment(when using typical “LSB-first” C++ compilers like GCC x86).
- CiliaC may have to reverse the order of bit field elements and add some padding
- Add your own filler (padding bits) to shift field elements/members on demand, e.g.
class Sign { UInt32:1 filler UInt32:31 bit0 }
- This way you can use
Functions
- Function declarations could start with the keyword
fn(Rust, Carbon, New Circle),fun(Kotlin), orfunction(Julia)
- Extension methods
- Possible, alternative syntax:
func toString (Int this) -> String
- Possible, alternative syntax:
- Function pointers
- Possible, alternative syntax variants:
- Variant B:
func((Int, Int) -> Int)* pointerToFunctionOfIntAndIntToInt// Closer to the function declaration but (too) many brackets
- Variant C:
(Int, Int -> Int)[Functions are only available as pointers, so you can omit “*”?]
- Variant D:
func*(Int->Int) pointerToFunctionOfIntAndIntToIntfunc*(Int) pointerToFunctionOfInt
- Variant E:
func*(Int, Int)->Int pointerToFunctionOfIntAndIntToInt(func*(Int, Int)->Int)[] arrayOfPointersToFunctionOfIntAndIntToInt
Function/Loop Parameter Passing
- If you want even the basic type to be different, we could write:
for Double d in [1, 2, 3] { ... }disconst Double
for String str in ["a", "b", "c"] { ... }strisconst String(notconst StringView&)strisconst String&(notconst StringView&)- TODO This doesn’t actually make sense here; you cannot get a (const) reference to a string when the underlying array is in fact a
StringView[].
- TODO This doesn’t actually make sense here; you cannot get a (const) reference to a string when the underlying array is in fact a
for inout String str in ["a", "b", "c"] { ... }strisString&- TODO This doesn’t actually make sense here; you cannot get a (mutable/non-const) reference to a string when the underlying array is in fact a
StringView[].
for copy String str in ["a", "b", "c"] { ... }strisString
Switch/Case
- Old behavior with implicit
fallthroughon demand.switch i fallthrough { case 1: case 2: case 3: case 4: case 5: print("1, 2, 3, 4, or 5") break default: print("default") }
Literals
true,falseare BoolNullcould be the null pointer, andNullTypeits type.- Shorter and more similar to
NULLin C.
- Shorter and more similar to
Signed Size
UIntas type for*.size()(i.e. still unsigned)
but with new rules for mixed integer arithmetic:- Unsigned +-*/ Signed -> Signed.
- Signed is therefore considered the “larger” type compared to unsigned
1isInt(signed)1uisUInt(unsigned)
- Therefore
if aUInt - 1 >= 0is a useful expression (as1is signed,aUInt - 1is signed, too) - But then also
aUInt + 1 == anInt
- Unsigned +-*/ Signed -> Signed.
- Or
Size-Size->SSize- Problem:
-results inSSize, but+results inSize?!
- Problem:
- The conversion of a negative number into
Sizeleads to an error instead of delivering a HUGE size.
- Note: In the end this just didn’t work out.
Operators
- Possible, alternative syntax for
pow(a, x):
a**x(as Python did) - Some more kinds of range literals could be useful:
8>..0:-1– 7, 6, 5, 4, 3, 2, 1, 0- RangeExclusiveStartByStep(8, 0, -1)
8>..0:-3– 7, 4, 1- RangeExclusiveStartByStep(8, 0, -3)
8..>0:-1– 8, 7, 6, 5, 4, 3, 2, 1- RangeExclusiveEndByStep(8, 0, -1)
8..>0:-1– 8, 7, 6, 5, 4, 3, 2, 1- RangeDownwardsExclusiveEndByStep(8, 0, -1)
- Incomplete ranges
0<..– RangeFromExclusiveStart(0)
- Incomplete range with step
8>..:-1– RangeFromExclusiveStartByStep(8, -1)8>..:-2– RangeFromExclusiveStartByStep(8, -2)
0<..2– RangeExclusiveStart(0, 2)- Range with negative step used for downwards iterating ranges:
2..0:-1– RangeWithStep(2, 0, -1)3>..0:-1– RangeExclusiveStartWithStep(3, 0, -1)- Incomplete ranges with negative step:
..1:-1– RangeToWithStep(1, -1)2..:-1– RangeFromWithStep(2, -1)3>..:-1– RangeFromExclusiveStartWithStep(3, -1)..:-1– RangeFullWithStep(-1)
- Note: Too complicated for too little benefit.
- Maybe remove
++i,--i,i++,i--?- as Python
- only offer/allow
i += 1,i -= 1
or even onlyi = i + 1,i = i - 1 - Note: No, Cilia is a C++ descendant after all.
Templates
- Class templates
- Partial template specialization could be written
class<type T, Int N> MyUniquePtr<T[N]> { ... destructor calls delete[] ... }
- Partial template specialization could be written
- Function templates
- Explicit function templates could be written as:
func<Number T> add(T x, y) -> T { return x + y } - Extension function templates could be written as
template<type T, Int N> func T[N]::size() -> Int { return N }template<type T, Int N> func T[N]::convertTo<type TOut>() -> TOut[N] { ... }
- Explicit function templates could be written as:
- Template type alias could be written as:
template<type T> using T::InArgumentType = const T&
Cilia Standard Library
- “Alias” for
- member variables could be written as
alias x = data[0], - member functions could use perfect forwarding,
- see stackoverflow.com/a/9864472
- but that would not work for virtual functions.
- member variables could be written as
String, Char & Unicode
- Code points could be represented by
UInt32or by a distinct typeCodePoint(==UInt32).- Would it be useful?
WideCharcould be useful for portable code (LinuxUInt32<-> WindowsUInt16)- But you may use
wchar_tthen.
- But you may use
- Alternative names/syntax to iterate over strings:
for codeUnit in "abc 🥸👮🏻".asCodeUnits()(a bit more explicit/clear than.asArray())- Is
byWord()(like in “word by word”) a better naming?for graphemeCluster in text.byGraphemeCluster()for codePoint in text.byCodePoint()for codeUnit in text.byCodeUnit()for codeUnit in text.byChar()for word in text.byWord()for line in text.byLine()for sentence in text.bySentence()
Arrays & ArrayViews
Int[] dynamicArrayOfIntegers- Also the syntax
[T] arr, as in Swift or Rust, has some merits.
And[3 T] arrfor fixed sized arrays would be fine for me (I don’t like[T;3] arr), but I’ll stick with the more traditionalT[] arr(like C# and Java). - May be confusing because it is so similar to fixed-size arrays,
but IMHO the inconsistency is already in C/C++:- in function declarations
int[]andint*are actually the same,
- but for local variables
int[]andint*mean different things:int array[3]andint array[] = { 1, 2, 3 }are used for in-place arrays,int* array = new int[3]is used for an int-array of unknown size.
- in function declarations
- Also the syntax
- Mixed forms of static and dynamic array may be useful:
Int[3,,]Int[3,4,]
(Smart) Pointers
- We may use some more (or just other) characters for the “special” pointers
- ASCII
Type> pointer(very difficult to read with template types, e.g.Matrix<Float64>> matrix)Type~ pointer(also used for binary not and destructor syntax)Type# pointerType% pointerType§ pointerType$ pointerType' pointerType. pointer
- More exotic characters
- (But a character that is difficult to find on the keyboard would not actually encourage people to use this syntax.)
- Latin-1
Type° pointerType¹ pointerType• pointerType› pointer
- Unicode variants of
T*Type*̂ pointerType*̄ pointerType*̇ pointer- (easy to confuse with
T*)
*plus other character(s)- (a bit long)
Type*^ pointerType*+ pointerType*. pointerType*° pointerType*¹ pointerType*+ pointerType*> pointerType*1> pointerType*¹> pointer- I don’t like this:
Type^* pointerType+* pointerType.* pointer
- ASCII
is, as, Casting
- Automatic casts
- As multiple inheritance is problematic here:
- In Cilia/C++, an object can be an instance of several base classes at once, whereby the pointer (sometimes) changes during casting.
- What if you still want/need to access the functions for a
Type objafterif obj is ParentA? - Therefore maybe better:
if obj is String str ...- as in C#
- As multiple inheritance is problematic here:
Versioning
Versioning of the Cilia source code could alternatively be done
- via file “.cilia_version” in a (project) directory,
- via file extension:
- “*.cilia2024” – Version from the year 2024
- “*.cilia2024b” – Second version from the year 2024
- “*.cilia_2024” – Version from the year 2024
- “*.cilia_2024b” – Second version from the year 2024
- “*.ciliaA”
- “*.ciliaB”