{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "

Previous

\n", "

Next

\n", "

Tour of Scala

\n", "
\n", "\n", "# Operators\n", "In Scala, operators are methods. Any method with a single parameter can be used as an _infix operator_. For example, `+` can be called with dot-notation:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "attributes": { "classes": [ "tut" ], "id": "" } }, "outputs": [ { "data": { "text/plain": [ "\u001b[36mres0\u001b[39m: \u001b[32mInt\u001b[39m = \u001b[32m11\u001b[39m" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "10.+(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However, it's easier to read as an infix operator:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "attributes": { "classes": [ "tut" ], "id": "" } }, "outputs": [ { "data": { "text/plain": [ "\u001b[36mres1\u001b[39m: \u001b[32mInt\u001b[39m = \u001b[32m11\u001b[39m" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "10 + 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Defining and using operators\n", "You can use any legal identifier as an operator. This includes a name like `add` or a symbol(s) like `+`." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "attributes": { "classes": [ "tut" ], "id": "" } }, "outputs": [ { "data": { "text/plain": [ "defined \u001b[32mclass\u001b[39m \u001b[36mVec\u001b[39m\n", "\u001b[36mvector1\u001b[39m: \u001b[32mVec\u001b[39m = \u001b[33mVec\u001b[39m(\u001b[32m1.0\u001b[39m, \u001b[32m1.0\u001b[39m)\n", "\u001b[36mvector2\u001b[39m: \u001b[32mVec\u001b[39m = \u001b[33mVec\u001b[39m(\u001b[32m2.0\u001b[39m, \u001b[32m2.0\u001b[39m)\n", "\u001b[36mvector3\u001b[39m: \u001b[32mVec\u001b[39m = \u001b[33mVec\u001b[39m(\u001b[32m3.0\u001b[39m, \u001b[32m3.0\u001b[39m)\n", "\u001b[36mres2_4\u001b[39m: \u001b[32mDouble\u001b[39m = \u001b[32m3.0\u001b[39m\n", "\u001b[36mres2_5\u001b[39m: \u001b[32mDouble\u001b[39m = \u001b[32m3.0\u001b[39m" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "case class Vec(val x: Double, val y: Double) {\n", " def +(that: Vec) = new Vec(this.x + that.x, this.y + that.y)\n", "}\n", "\n", "val vector1 = Vec(1.0, 1.0)\n", "val vector2 = Vec(2.0, 2.0)\n", "\n", "val vector3 = vector1 + vector2\n", "vector3.x // 3.0\n", "vector3.y // 3.0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The class Vec has a method `+` which we used to add `vector1` and `vector2`. Using parentheses, you can build up complex expressions with readable syntax. Here is the definition of class `MyBool` which includes methods `and` and `or`:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "attributes": { "classes": [ "tut" ], "id": "" } }, "outputs": [ { "data": { "text/plain": [ "defined \u001b[32mclass\u001b[39m \u001b[36mMyBool\u001b[39m" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "case class MyBool(x: Boolean) {\n", " def and(that: MyBool): MyBool = if (x) that else this\n", " def or(that: MyBool): MyBool = if (x) this else that\n", " def negate: MyBool = MyBool(!x)\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is now possible to use `and` and `or` as infix operators:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "attributes": { "classes": [ "tut" ], "id": "" } }, "outputs": [ { "data": { "text/plain": [ "defined \u001b[32mfunction\u001b[39m \u001b[36mnot\u001b[39m\n", "defined \u001b[32mfunction\u001b[39m \u001b[36mxor\u001b[39m" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def not(x: MyBool) = x.negate\n", "def xor(x: MyBool, y: MyBool) = (x or y) and not(x and y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This helps to make the definition of `xor` more readable.\n", "\n", "## Precedence\n", "When an expression uses multiple operators, the operators are evaluated based on the priority of the first character:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```\n", "(characters not shown below)\n", "* / %\n", "+ -\n", ":\n", "= !\n", "< >\n", "&\n", "^\n", "|\n", "(all letters)\n", "```\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This applies to functions you define. For example, the following expression:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```scala\n", "a + b ^? c ?^ d less a ==> b | c\n", "```\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Is equivalent to" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```scala\n", "((a + b) ^? (c ?^ d)) less ((a ==> b) | c)\n", "```\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`?^` has the highest precedence because it starts with the character `?`. `+` has the second highest precedence, followed by `==>`, `^?`, `|`, and `less`.\n", "

Previous

\n", "

Next

\n", "

Tour of Scala

\n", "
" ] } ], "metadata": { "kernelspec": { "display_name": "Scala (2.13)", "language": "scala", "name": "scala213" }, "language_info": { "codemirror_mode": "text/x-scala", "file_extension": ".scala", "mimetype": "text/x-scala", "name": "scala", "nbconvert_exporter": "script", "version": "2.13.1" } }, "nbformat": 4, "nbformat_minor": 4 }