Kotlin/JUnit advertise the use of backticked function names for tests. I've discovered that you can also use backticked class names...
But I can't find any reference. Is thing something in the Kotlin specification, or just a "may go away soon" unintended feature?
code example:
#Nested
inner class `when the entity path only specifies one location` {
#BeforeEach
fun setup() {
entity = Entity(
id = "entityid1",
name = "entity1",
type = "type",
team = TeamColor.BLUE,
currentLocation = Location(0.0, 10.0, 0.0),
path = EntityPath(
startTime = "00:00:00",
timeLocation = listOf(
TimeLocation("00:00:00", Location(0.0, 10.0, 0.0)),
)
),
)
}
#Test
fun `it returns the first (only) location`() {
val actualLocation = entityLocator.getEntityLocation(entity, calculation);
val expectedLocation = Location(0.0, 10.0, 0.0)
assertEquals(actualLocation, expectedLocation);
}
}
Backticks are part of the general language syntax: anywhere you can write a name (whether it's a function, class, property, variable or whatever), you can put it in backticks and include almost any characters (except for newlines, or backticks themselves).
(The original use case may have been for interoperability with Java methods having the same names as Kotlin keywords, such as System.out; but it's more generally useful, as shown in the tests you quote.)
It's documented in the language grammar itself — in the definition of Identifier — so it's an intended part of the language, and unlikely to go away!
Update:
But although Kotlin is guaranteed to support backticks for all identifiers, does that mean you should choose names that need them? In most situations, it's not recommended.
The two main places where you might see them are:
Methods, fields, and packages from the Java standard library or from other Java libraries, that are valid in Java but not in Kotlin — usually because they're reserved words in Kotlin. (For example: System.out, and Mockito's when method.) Backticks are of course necessary for these, as there's no other way to access them from Kotlin.
Method names in unit tests, as demonstrated in this question. This is a matter of style. Some people like long method names with embedded spaces and punctuation, that describe what's being tested in plain English; they also like test methods that look unmistakably different from the code being tested. Other people find them ugly, awkward, and hard to read.As gotube says, the Kotlin coding conventions specifically allow test method names with spaces. But they don't require it; you're free to follow the usual conventions if you prefer. And they only allow it for method names, not for names of classes, objects, packages, properties, or local variables — so it's best to stick to the usual conventions for all those other identifiers, even when writing tests.
Kotlin coding convention specifies that backticks are for use in tests only:
Names for test methods
In tests (and only in tests), you can use method names with spaces enclosed in backticks.
Related
Is there a way to enforce 1..* parameters in Kotlin that will still allow the spread operator?
I've tried:
class Permission(
// 1..n compliance
accessiblePage: Webpage,
vararg accessiblePages: Webpage
) {
And that does enforce 1..*, but it also means that Permission(*pages) won't work, so that's a pretty awkward interface.
Is there an easy way to enforce 1..* without a runtime constructor error?
There is, unfortunately, no way to check this in Kotlin at compile time aside from the way you mentioned. Since vararg parameters are really just syntactic sugar for an array, your code is essentially
class Permission (
accessiblePage: Webpage,
accessiblePages: Array<Webpage>
)
So the question then becomes "Can you ensure that an array has at least one element in it at compile time?" For most languages, that's a clear no, although the Kotlin team did at one point experiment with it:
[C]urrently, Kotlin compiler doesn't collect static information about
collections size. FYI, at some point Kotlin team tried to collect such
information and use it for warnings about possible
IndexOutOfBoundException and stuff like that, but it was found that
there were a very little demand on such diagnostics in real-life
projects, so, given complexity of such analysis, it was abandoned[.]
(https://github.com/Kotlin/KEEP/issues/139#issuecomment-405551324)
It's possible that this metadata will be added at some point, but you shouldn't expect it soon.
That said, you could always combine a runtime check in the case of an Array with an overloaded signature in the case of varargs. This would mean that your vararg example would work the same, but passing an array to the function would subject it to a runtime check (you'd also not have to use the spread operator anymore):
class Permission (
accessiblePage: Webpage
vararg accessiblePages: Webpage
) {
constructor(accessiblePages: Array<Webpage>) {
require(accessiblePages.isNotEmpty()) {
"Must have at least one accessible page."
}
}
}
called like
val permission1 = Permission(Webpage(), Webpage())
val permission2 = Permission() // Would fail at compile time
val pages = arrayOf()
val permission3 = Permission(pages) // Would fail at runtime. Note also the lack of the spread operator.
I was having a look at the Arrow library found here. Why would ever want to use an Option type instead of Kotlin's built in nullables?
I have been using the Option data type provided by Arrow for over a year, and there at the beginning, we did the exact same question to ourselves. The answer follows.
Option vs Nullable
If you compare just the option data type with nullables in Kotlin, they are almost even. Same semantics (there is some value or not), almost same syntax (with Option you use map, with nullables you use safe call operator).
But when using Options, you enable the possibility to take benefits from the arrow ecosystem!
Arrow ecosystem (functional ecosystem)
When using Options, you are using the Monad Pattern. When using the monad pattern with libraries like arrow, scala cats, scalaz, you can take benefits from several functional concepts. Just 3 examples of benefits (there is a lot more than that):
1. Access to other Monads
Option is not the only one! For instance, Either is a lot useful to express and avoid to throw Exceptions. Try, Validated and IO are examples of other common monads that help us to do (in a better way) things we do on typical projects.
2. Conversion between monads + abstractions
You can easily convert one monad to another. You have a Try but want to return (and express) an Either? Just convert to it. You have an Either but doesn't care about the error? Just convert to Option.
val foo = Try { 2 / 0 }
val bar = foo.toEither()
val baz = bar.toOption()
This abstraction also helps you to create functions that doesn't care about the container (monad) itself, just about the content. For example, you can create an extension method Sum(anyContainerWithBigDecimalInside, anotherContainerWithBigDecimal) that works with ANY MONAD (to be more precise: "to any instance of applicative") this way:
fun <F> Applicative<F>.sum(vararg kinds: Kind<F, BigDecimal>): Kind<F, BigDecimal> {
return kinds.reduce { kindA, kindB ->
map(kindA, kindB) { (a, b) -> a.add(b) }
}
}
A little complex to understand, but very helpful and easy to use.
3. Monad comprehensions
Going from nullables to monads is not just about changing safe call operators to map calls. Take a look at the "binding" feature that arrow provides as the implementation of the pattern "Monad Comprehensions":
fun calculateRocketBoost(rocketStatus: RocketStatus): Option<Double> {
return binding {
val (gravity) = rocketStatus.gravity
val (currentSpeed) = rocketStatus.currentSpeed
val (fuel) = rocketStatus.fuel
val (science) = calculateRocketScienceStuff(rocketStatus)
val fuelConsumptionRate = Math.pow(gravity, fuel)
val universeStuff = Math.log(fuelConsumptionRate * science)
universeStuff * currentSpeed
}
}
All the functions used and also the properties from rocketStatus parameter in the above example are Options. Inside the binding block, the flatMap call is abstracted for us. The code is a lot easier to read (and write) and you don't need to check if the values are present, if some of them is not, the computation will stop and the result will be an Option with None!
Now try to imagine this code with null verifications instead. Not just safe call operators but also probably if null then return code paths. A lot harder isn't it?
Also, the above example uses Option but the true power about monad comprehensions as an abstraction is when you use it with monads like IO in which you can abstract asynchronous code execution in the exact same "clean, sequential and imperative" way as above :O
Conclusion
I strongly recommend you to start using monads like Option, Either, etc as soon as you see the concept fits the semantics you need, even if you are not sure if you will take the other big benefits from the functional ecosystem or if you don't know them very well yet. Soon you'll be using it without noticing the learning-curve. In my company, we use it in almost all Kotlin projects, even in the object-oriented ones (which are the majority).
Disclaimer: If you really want to have a detailed talk about why Arrow is useful, then please head over to https://soundcloud.com/user-38099918/arrow-functional-library and listen to one of the people who work on it. (5:35min)
The people who create and use that library simple want to use Kotlin differently than the people who created it and use "the Option datatype similar to how Scala, Haskell and other FP languages handle optional values".
This is just another way of defining return types of values that you do not know the output of.
Let me show you three versions:
nullability in Kotlin
val someString: String? = if (condition) "String" else null
object with another value
val someString: String = if (condition) "String" else ""
the Arrow version
val someString: Option<String> = if (condition) Some("String") else None
A major part of Kotlin logic can be to never use nullable types like String?, but you will need to use it when interopting with Java. When doing that you need to use safe calls like string?.split("a") or the not-null assertion string!!.split("a").
I think it is perfectly valid to use safe calls when using Java libraries, but the Arrow guys seem to think different and want to use their logic all the time.
The benefit of using the Arrow logic is "empowering users to define pure FP apps and libraries built atop higher order abstractions. Use the below list to learn more about Λrrow's main features".
One thing other answers haven't mentioned: you can have Option<Option<SomeType>> where you can't have SomeType??. Or Option<SomeType?>, for that matter. This is quite useful for compositionality. E.g. consider Kotlin's Map.get:
abstract operator fun get(key: K): V?
Returns the value corresponding to the given key, or null if such a key is not present in the map.
But what if V is a nullable type? Then when get returns null it can be because the map stored a null value for the given key or because there was no value; you can't tell! If it returned Option<V>, there wouldn't be a problem.
What are the backticks used for in the snippet below?
Why add them around the fun is(amount:Int ):Boolean { ... }?
verifier.`is`(amount)
It's because is is a reserved keyword in Kotlin. Since Kotlin is supposed to be interoperable with Java and is is a valid method (identifier) name in Java, the backticks are used to escape the method so that it can be used as a method without confusing it as a keyword. Without it it will not work because it would be invalid syntax.
This is highlighted in the Kotlin documentation:
Escaping for Java identifiers that are keywords in Kotlin
Some of the Kotlin keywords are valid identifiers in Java: in, object, is, etc. If a Java library uses a Kotlin keyword for a method, you can still call the method escaping it with the backtick (`) character
foo.`is`(bar)
Useful for tests
Backticks are very useful in tests for long function names:
#Test
fun `adding 3 and 4 should be equal to 7`() {
assertEquals(calculator.add(3, 4), 7)
}
This makes the function names more readable. We can add spaces and other special characters in the function names. However, remember to use it only in tests, it's against the Kotlin coding conventions of the regular code.
It allows you to call a Java method whose name is a Kotlin keyword. It won't work if you leave out the backticks.
The backtick are a "workaround" to allow you to call methods that have a name representing a Kotlin keyword.
See kotlinlang:
Some of the Kotlin keywords are valid identifiers in Java: in, object, is, etc. If a Java library uses a Kotlin keyword for a method, you can still call the method escaping it with the backtick (`) character
is in list of Kotlin reserved words
To use Kotlin reserved word (such as is or object) for function/class name you should wrap it to backticks
Some of the Kotlin keywords are valid identifiers in Java: in, object, is, etc. If a Java library uses a Kotlin keyword for a method, you can still call the method escaping it with the backtick (`) character
https://kotlinlang.org/docs/reference/java-interop.html
I am wondering if there exists already some naming conventions for Ocaml, especially for names of constructors, names of variables, names of functions, and names for labels of record.
For instance, if I want to define a type condition, do you suggest to annote its constructors explicitly (for example Condition_None) so as to know directly it is a constructor of condition?
Also how would you name a variable of this type? c or a_condition? I always hesitate to use a, an or the.
To declare a function, is it necessary to give it a name which allows to infer the types of arguments from its name, for example remove_condition_from_list: condition -> condition list -> condition list?
In addition, I use record a lot in my programs. How do you name a record so that it looks different from a normal variable?
There are really thousands of ways to name something, I would like to find a conventional one with a good taste, stick to it, so that I do not need to think before naming. This is an open discussion, any suggestion will be welcome. Thank you!
You may be interested in the Caml programming guidelines. They cover variable naming, but do not answer your precise questions.
Regarding constructor namespacing : in theory, you should be able to use modules as namespaces rather than adding prefixes to your constructor names. You could have, say, a Constructor module and use Constructor.None to avoid confusion with the standard None constructor of the option type. You could then use open or the local open syntax of ocaml 3.12, or use module aliasing module C = Constructor then C.None when useful, to avoid long names.
In practice, people still tend to use a short prefix, such as the first letter of the type name capitalized, CNone, to avoid any confusion when you manipulate two modules with the same constructor names; this often happen, for example, when you are writing a compiler and have several passes manipulating different AST types with similar types: after-parsing Let form, after-typing Let form, etc.
Regarding your second question, I would favor concision. Inference mean the type information can most of the time stay implicit, you don't need to enforce explicit annotation in your naming conventions. It will often be obvious from the context -- or unimportant -- what types are manipulated, eg. remove cond (l1 # l2). It's even less useful if your remove value is defined inside a Condition submodule.
Edit: record labels have the same scoping behavior than sum type constructors. If you have defined a {x: int; y : int} record in a Coord submodule, you access fields with foo.Coord.x outside the module, or with an alias foo.C.x, or Coord.(foo.x) using the "local open" feature of 3.12. That's basically the same thing as sum constructors.
Before 3.12, you had to write that module on each field of a record, eg. {Coord.x = 2; Coord.y = 3}. Since 3.12 you can just qualify the first field: {Coord.x = 2; y = 3}. This also works in pattern position.
If you want naming convention suggestions, look at the standard library. Beyond that you'll find many people with their own naming conventions, and it's up to you to decide who to trust (just be consistent, i.e. pick one, not many). The standard library is the only thing that's shared by all Ocaml programmers.
Often you would define a single type, or a single bunch of closely related types, in a module. So rather than having a type called condition, you'd have a module called Condition with a type t. (You should give your module some other name though, because there is already a module called Condition in the standard library!). A function to remove a condition from a list would be Condition.remove_from_list or ConditionList.remove. See for example the modules List, Array, Hashtbl,Map.Make`, etc. in the standard library.
For an example of a module that defines many types, look at Unix. This is a bit of a special case because the names are mostly taken from the preexisting C API. Many constructors have a short prefix, e.g. O_ for open_flag, SEEK_ for seek_command, etc.; this is a reasonable convention.
There's no reason to encode the type of a variable in its name. The compiler won't use the name to deduce the type. If the type of a variable isn't clear to a casual reader from the context, put a type annotation when you define it; that way the information provided to the reader is validated by the compiler.
There are many different styles of variable names that I've come across over the years.
The current wikipedia entry on naming conventions is fairly light...
I'd love to see a concise catalog of variable naming-conventions, identifying it by a name/description, and some examples.
If a convention is particularly favored by a certain platform community, that would be worth noting, too.
I'm turning this into a community wiki, so please create an answer for each convention, and edit as needed.
The best naming convention set that I've seen is in the book "Code Complete" Steve McConnell has a great section in there about naming conventions and lots of examples. His examples run through a number of "best practices" for different languages, but ultimately leave it up to the developer, dev manager, or architect to decide the specific action.
PEP8 is the style guide for Python code that is part of the standard library which is relatively influential in the Python community. For bonus points, in addition to covering the naming conventions used by the Python standard library, it provides an overview of naming conventions in general.
According to PEP8: variables, instance variables, functions and methods in the standard library are supposed to use lowercase words separated by underscores for readability:
foo
parse_foo
a_long_descriptive_name
To distinguish a name from a reserved word, append an underscore:
in_
and_
or_
Names that are weakly private (not imported by 'from M import *') start with a single underscore. Names whose privacy is enforced with name mangling start with double underscores.:
_some_what_private
__a_slightly_more_private_name
Names that are Python 'special' methods start and end with double underscores:
__hash__ # hash(o) = o.__hash__()
__str__ # str(o) = o.__str__()
Sun published a list of variable name conventions for Java here. The list includes conventions for naming packages, classes, interfaces, methods, variables, and constants.
The section on variables states
Except for variables, all instance, class, and class constants are in mixed case with a lowercase first letter. Internal words start with capital letters. Variable names should not start with underscore _ or dollar sign $ characters, even though both are allowed.
Variable names should be short yet meaningful. The choice of a variable name should be mnemonic- that is, designed to indicate to the casual observer the intent of its use. One-character variable names should be avoided except for temporary "throwaway" variables. Common names for temporary variables are i, j, k, m, and n for integers; c, d, and e for characters.
Some examples include
int i;
char c;
float myWidth;
Whatever your naming convention is, it usually do not allow you to easily distinguish:
instance (usually private) variable
local variables (used as parameters or local to a function)
I use a naming convention based on a the usage of indefinite article (a, an, some) for local variables, and no article for instance variables, as explained in this question about variable prefix.
So a prefix (either my way, or any other prefix listed in that question) can be one way of refining variable naming convention.
I know your question is not limited on variables, I just wanted to point out that part of naming convention.
There is, the "Java Programmers Phrasebook" by Einar Hoest.
He analysed the grammatical structure of method names together with the structure of the method bodies, and collected information such as:
add-[noun]-* These methods often have parameters and create objects.
They very rarely return field values.
The phrase appears in practically all
applications.
etcetera ... collected from hundreds of open-source projects.
For more background information, please refer to his SLE08 paper.