-
Notifications
You must be signed in to change notification settings - Fork 0
1. Features
This pages enumerates all Marcel's features.
All titles annotated with NYI means that the features described by the section and its sub-sections are is Not Yet Implemented
You can declare/assign a variable like you would in Java
// declaration
int myInteger = 1
float myFloat = 2f
// assignments
myInteger = 3
def (String a, String b) = "A B".split(" ")
When you declare a variable, you must always specify a value
Marcel supports the following primitive types
- void
- boolean
- byte
- int
- long
- float
- double
Marcel supports classes. You can use all existing Java classes from the JDK.
You can define classes like in Java
class Foo {
}
You can specify variables in String
"$firstName $lastName is $age years old"
If you need to access a property, use the brackets
"${person.firstName} ${person.lastName} is ${person.age} years old"
A truthy value is a value that is considered true for an if, or a while. A falsey value is a value that is considered false in those places.
The only falsey values are the following:
null
Optional.empty()
- An empty collection
- An empty array
Any other value is truthy.
You can also override the truth for a class if you define a function fun truthy() bool
In Java, Ifs are statement but in Marcel you can use them as expression, similar as Kotlin's Ifs. If an if/else if/else has only one statement in it, you can omit brackets
int a = if (something()) 1 else if (somethingElse()) 2 else 3
if (a == 1) {
a++
println("foo")
} else {
a--
println("bar")
}
Marcel truth allows you to declare variable in an if
condition, and execute the code block if the variable is truthy
if (Something result = fetchSomething()) {
println("Fetched $result")
}
You can also deconstruct Optional values such as in the below example (NYI)
// assuming getOptionalInteger() returns an Optional<Integer>
if (Integer result = getOptionalInteger()) {
println(result)
}
There are different ways to iterate over values
The Java for i is compatible with Marcel
for (int i = 0; i < 10; i++) {
println(i)
}
The in
keyword allows to iterate over values in an array, or any objects implementing Iterable (meaning all Collections).
int[] ints = getInts()
for (int i in ints) {
println(i)
}
Marcel also have a Ranges, allowing you to iterate with the below syntax
// inclusive range
for (int i in 0..9) {
println(i)
}
// exclusive range
for (int i in 0..<10) {
println(i)
}
// also work in reverse orde
for (int i in 9..0) {
println(i)
}
// exclusive range
for (int i in 10>..0) {
println(i)
}
TODO
You can use ternary expression. Marcel truth also applies in them, meaning you can specify values of any type.
The below code will print 2
int a = Optional.empty() ? foo() : bar()
println(a)
fun foo() int {
return 1
}
fun bar() int {
return 2
}
Use the fun
keyword to define functions
fun sum(int a, int b) int {
return a + b
}
fun foo() {
// do nothing
}
int result = sum(1, 2)
In marcel, there are 3 kinds of visibility.
-
public
-> which refers to Java's public visibility. Your class/method may be accessible from any package -
protected
-> which refers to Java's protected visibility. Your class/method may only be accessible from other classes in the same package or inheriting your class -
internal
-> which refers to Java's package-private visibility. Your class/method may only be accessible from classes in the same package -
private
-> Your method may be accessible only from the class it was defined in
To specify a visibility for your method, put it before the fun
keyword.
private fun sum(int a, int b) int {
return a + b
}
Functions are public
by default.
Function arguments can have default constant values
You can specify method argument names when calling a function. To use sum
method defined above we would do.
int result = sum(a = 1, b = 2)
Function parameters can have default values, which are used when you skip the corresponding argument.
fun sum(int a = 0, int b = 8) int {
return a + b
}
sum(a = 2)
sum(b = 5)
sum(a = 2, b = 5)
A function can return multiple values
fun foo() (int, int) {
return a + 8, b + 10
}
int a, b = foo()
You can declare litteral arrays like in the below example
long[] array = [1, 2, 3, 4]
Object[] = ["some", 1, new Object()]
Marcel allows to use collections with primitive elements.
All Collections of primitive types can be declared using the lowercase type's name of Java equivalent
list<int> list = [1, 2, 3, 4]
set<long> set = [1d, 2, 4d, 4d]
// this set will contain 1, 2 and 4
You can declare a set using a similar syntax. The given array will be transformed into a set, and all duplcated elements will be filtered
map<float, Object> map = {1.3: "1", 1.4: "2"}
When dealing with nullable/Optional variables, this operator can be handy to have a default value.
String displayName = user.name ?: 'Anonymous'
The default value will be used if the variable is null
or it is an empty Optional.
You can also use this operator to return from a function when the value is null
String displayName = user.name ?: return
The Safe Navigation operator is used to avoid a NullPointerException. Typically when you have a reference to an object you might need to verify that it is not null before accessing methods or properties of the object. To avoid this, the safe navigation operator will simply return null instead of throwing an exception, like so
Person person = fetchPerson()
String name = person?.name
This operator allows you to access safely an array/List by index, fallbacking to null if the index is out of bounds
int value = array?[10] ?: 0
You can define operators for your classes like in Groovy
Define the appropriate function on your class to be able to use the corresponding operator on your class instances.
Define comments like you would in Java. //
for a single line comment, and /* ... */
for a multi-line comment
You can get and set properties dynamically in your script. Such properties are accessible in your script's main function, and all non-static functions of your script
set a = 1
set b = [1, 2]
// do some stuff
int something = get a
// enforce type checking with the 'as' keyword
list<int> list = get b as list<int>
Allows to get dynamically properties dynamically, like in Groovy (TBD)
keyword as
This will do its best to cast at compile time (e.g. for arrays to collections) but if not it will add a cast check at runtime