Skip to content

Instantly share code, notes, and snippets.

@jim-collins
Last active March 30, 2018 19:50
Show Gist options
  • Save jim-collins/c1b854ea0f3c2ff8c28032d9820f8b41 to your computer and use it in GitHub Desktop.
Save jim-collins/c1b854ea0f3c2ff8c28032d9820f8b41 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Scala Coding Standards and Practices\n",
"\n",
"## Introduction\n",
"\n",
"This Scala notebook documents coding standards and best practices that should be adopted by the Home Office RMP team.\n",
"\n",
"This document is best viewed as a [Jupyter Notebook](https://jupyter.org/index.html) where you can edit and run the code.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Some imports for the Libraries used"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/plain": [
"\u001b[32mimport \u001b[39m\u001b[36m$ivy.$ \n",
"\u001b[39m"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import $ivy.`org.vegas-viz::vegas:0.3.9`\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Naming Standards\n",
"\n",
"The [Scala Documentation](https://docs.scala-lang.org/style/naming-conventions.html) has an excellent guide for naming conventions and this should be adhered to.\n",
"\n",
"One point worth empahsing is on naming convention for [constants](https://docs.scala-lang.org/style/naming-conventions.html#constants-values-variable-and-methods) with regards to pattern matching. A constant pattern only matches itself however if the constant does not begin with an uppdercase letter then the compiler treats it as a variable pattern, as can be seen in the example below the const **_anotherConst_** is treated as a variable. In fact the normal Scala compiler would not even compile because patterns after a variable pattern can never match."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\u001b[36mSomeConst\u001b[39m: \u001b[32mInt\u001b[39m = \u001b[32m7\u001b[39m\n",
"\u001b[36manotherConst\u001b[39m: \u001b[32mInt\u001b[39m = \u001b[32m8\u001b[39m\n",
"defined \u001b[32mfunction\u001b[39m \u001b[36mmatchInt\u001b[39m\n",
"\u001b[36ms1\u001b[39m: \u001b[32mString\u001b[39m = \u001b[32m\"matched to 5\"\u001b[39m\n",
"\u001b[36ms2\u001b[39m: \u001b[32mString\u001b[39m = \u001b[32m\"7 matched to 7\"\u001b[39m\n",
"\u001b[36ms3\u001b[39m: \u001b[32mString\u001b[39m = \u001b[32m\"9 matched to 8\"\u001b[39m"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"final val SomeConst = 7\n",
"final val anotherConst = 8\n",
"\n",
"def matchInt(i: Int) = i match {\n",
" case 5 => \"matched to 5\"\n",
" case SomeConst => s\"$SomeConst matched to 7\"\n",
" case anotherConst => s\"$anotherConst matched to 8\"\n",
" case _ => \"no match\"\n",
"}\n",
"\n",
"val s1 = matchInt(5)\n",
"val s2 = matchInt(7)\n",
"val s3 = matchInt(9)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Type Inference\n",
"\n",
"With Scala type inference you get the benefits of a static type system which feels like it is dynamically typed.\n",
"\n",
"### Avoid unnecessary type annotations\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\u001b[36ml\u001b[39m: \u001b[32mList\u001b[39m[\u001b[32mInt\u001b[39m] = \u001b[33mList\u001b[39m(\u001b[32m1\u001b[39m, \u001b[32m2\u001b[39m, \u001b[32m3\u001b[39m)\n",
"\u001b[36ml2\u001b[39m: \u001b[32mList\u001b[39m[\u001b[32mInt\u001b[39m] = \u001b[33mList\u001b[39m(\u001b[32m123\u001b[39m)"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"val l: List[Int] = List[Int](1,2,3)\n",
"val l2 = List(123)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Use curried functions to help the inferencer"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"cmd9.sc:2: missing parameter type for expanded function ((x$1) => x$1.$greater$eq(2))\n",
"val res9_1 = exists1(List(1,2,3), _ >= 2)\n",
" ^"
]
},
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"Compilation Failed"
]
}
],
"source": [
"def exists1[T](l: List[T], f: T => Boolean) = l.exists(f)\n",
"exists1(List(1,2,3), _ >= 2)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"defined \u001b[32mfunction\u001b[39m \u001b[36mexists1\u001b[39m\n",
"\u001b[36mres10_1\u001b[39m: \u001b[32mBoolean\u001b[39m = \u001b[32mtrue\u001b[39m\n",
"defined \u001b[32mfunction\u001b[39m \u001b[36mexists2\u001b[39m\n",
"\u001b[36mres10_3\u001b[39m: \u001b[32mBoolean\u001b[39m = \u001b[32mtrue\u001b[39m"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def exists1[T](l: List[T], f: T => Boolean) = l.exists(f)\n",
"exists1(List(1,2,3), (i: Int) => i >= 2)\n",
"\n",
"def exists2[T](l: List[T])(f: T => Boolean) = l.exists(f)\n",
"exists2(List(1,2,3))(_ >= 2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Annotate methods with the return type if it is not apparent"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Don't use return"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Don't use null"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Avoid throwing exceptions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Futures"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Scala",
"language": "scala",
"name": "scala"
},
"language_info": {
"codemirror_mode": "text/x-scala",
"file_extension": ".scala",
"mimetype": "text/x-scala",
"name": "scala211",
"nbconvert_exporter": "script",
"pygments_lexer": "scala",
"version": "2.11.11"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment