Last active
March 30, 2018 19:50
-
-
Save jim-collins/c1b854ea0f3c2ff8c28032d9820f8b41 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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