├── .gitattributes ├── .gitignore ├── README.md ├── Scripts └── MessagesDemo.scala └── notebooks ├── Scala-019-Higher-OrderFunctions.ipynb └── Scala-020-VarArgs-NamedArgumentsDefaultValues.ipynb /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Scala Tutorials 2 | Example Code & Notebooks for Scala Tutorials @ Learning Journal 3 | Visit https://learningjournal.guru/ for Video Tutorials 4 | 5 | -------------------------------------------------------------------------------- /Scripts/MessagesDemo.scala: -------------------------------------------------------------------------------- 1 | class Message(p_id:String, p_msg:String) { 2 | val id = p_id; 3 | val msg = p_msg; 4 | } 5 | 6 | object Message{ 7 | def apply(id:String, msg:String) = new Message(id,msg) 8 | 9 | def unapply(m:Message) :Option[(String,String)] = { 10 | if (m == null) None 11 | else Some(m.id, m.msg) 12 | } 13 | } 14 | 15 | object EmailAddress { 16 | def apply(uname: String, dname: String) = uname + "@" + dname 17 | 18 | def unapply(str: String): Option[(String, String)] = { 19 | val parts = str split "@" 20 | if (parts.length == 2) Some(parts(0), parts(1)) else None 21 | } 22 | } 23 | 24 | def testMessagePattern(l:List[Message]):String = { 25 | l match { 26 | case Nil => "Not found" 27 | case Message(EmailAddress(u1,d1),_) ::Message(EmailAddress(u2,d2),_) :: _ if(u1==u2) => u1 + " got two successive emails" 28 | case h::t => testMessagePattern(t) 29 | } 30 | } 31 | 32 | val messageList = List( 33 | Message("tom@gmail.com","Message text 1"), 34 | Message("7742394590","Message text 2"), 35 | Message("8326192398","Message text 3"), 36 | Message("lisa@gmail.com","Message text 4"), 37 | Message("lisa@yahoo.com","Message text 5"), 38 | Message("harry@gmail.com","Message text 6") 39 | ) 40 | 41 | println(testMessagePattern(messageList)) 42 | -------------------------------------------------------------------------------- /notebooks/Scala-019-Higher-OrderFunctions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "

Scala-019 - Higher Order Functions

\n", 8 | "\n", 9 | "This tutorial covers Higher Order Function syntax in Scala. The notebook is a companion for the Video Tutorial. \n", 10 | "\n", 11 | "A complete video compilation is available @ [Youtube](https://www.youtube.com/playlist?list=PLkz1SCf5iB4dZ2RNKCu7W9o2OtZweGY6x). " 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Higher-Order Functions" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "Higher-order functions in Scala can do following things.\n", 26 | "1. They can take a function as an argument.\n", 27 | "2. They can return a function as a value." 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "### How to create a function that takes another function as an argument?" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "You can do this by defining an argument type annotation as a function type." 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "#### Example" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 1, 54 | "metadata": { 55 | "collapsed": true 56 | }, 57 | "outputs": [], 58 | "source": [ 59 | "def intDecorator(x:Int, f: Int => String) = f(x)" 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "The argument ***f*** has a function type (***Int => String***). \n", 67 | "\n", 68 | "So the ***intDecorator*** takes a function as a second argument. The type of the function must be ***Int => String***. \n", 69 | "\n", 70 | "You can call it as shown below." 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": 6, 76 | "metadata": {}, 77 | "outputs": [ 78 | { 79 | "data": { 80 | "text/plain": [ 81 | "[5]" 82 | ] 83 | }, 84 | "execution_count": 6, 85 | "metadata": {}, 86 | "output_type": "execute_result" 87 | } 88 | ], 89 | "source": [ 90 | "intDecorator(5, (y:Int) => \"[\" + y + \"]\" )" 91 | ] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "metadata": {}, 96 | "source": [ 97 | "### How to create a function that returns another function?" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "You can do this by creating a ***function literal*** (anonymous function) as the last statement of a function." 105 | ] 106 | }, 107 | { 108 | "cell_type": "markdown", 109 | "metadata": {}, 110 | "source": [ 111 | "#### Example" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 2, 117 | "metadata": { 118 | "collapsed": true 119 | }, 120 | "outputs": [], 121 | "source": [ 122 | "def greetSomeone(prefix:String) = { \n", 123 | " println(\"Got a prefix \" + prefix)\n", 124 | " (name:String) => println(prefix + \" \" + name)\n", 125 | "}" 126 | ] 127 | }, 128 | { 129 | "cell_type": "markdown", 130 | "metadata": {}, 131 | "source": [ 132 | "The last statement of the function is a *function literal*. Scala will automatically return the result of the last expression, i.e., It will return a function value. \n", 133 | "\n", 134 | "You can call this function as shown below." 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": 3, 140 | "metadata": {}, 141 | "outputs": [ 142 | { 143 | "name": "stdout", 144 | "output_type": "stream", 145 | "text": [ 146 | "Got a prefix Hello\n", 147 | "Hello Prashant\n" 148 | ] 149 | } 150 | ], 151 | "source": [ 152 | "val hiSomeone = greetSomeone(\"Hello\")\n", 153 | "hiSomeone(\"Prashant\")" 154 | ] 155 | }, 156 | { 157 | "cell_type": "markdown", 158 | "metadata": {}, 159 | "source": [ 160 | "

Practice Exercise

\n", 161 | "*****************************" 162 | ] 163 | }, 164 | { 165 | "cell_type": "markdown", 166 | "metadata": {}, 167 | "source": [ 168 | "### 1. Exercise\n", 169 | "\n", 170 | "Create a function that takes an integer *x* as an input, and then it does following things.\n", 171 | "1. Print the SQRT of the input parameter *x*\n", 172 | "2. Returns a function that takes another integer *y* as input\n", 173 | "\n", 174 | "The returned function computes and returns the SQRT of *x + y*" 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "metadata": {}, 180 | "source": [ 181 | "### 2. Exercise\n", 182 | "\n", 183 | "A function definition is given below.\n", 184 | "How can you return a local function f2?" 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": 4, 190 | "metadata": { 191 | "collapsed": true 192 | }, 193 | "outputs": [], 194 | "source": [ 195 | "def f1(x:Int) = {\n", 196 | " println(s\"SQRT of $x is \" + Math.sqrt(x))\n", 197 | " def f2(y:Int) = Math.sqrt(x+y)\n", 198 | "}" 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "metadata": {}, 204 | "source": [ 205 | "### 3. Exercise\n", 206 | "\n", 207 | "A function definition is given below.\n", 208 | "Create an equivalent function by removing all optional parts." 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": 5, 214 | "metadata": {}, 215 | "outputs": [ 216 | { 217 | "data": { 218 | "text/plain": [ 219 | "4.47213595499958" 220 | ] 221 | }, 222 | "execution_count": 5, 223 | "metadata": {}, 224 | "output_type": "execute_result" 225 | } 226 | ], 227 | "source": [ 228 | "val f1: Int => (Int => Double) = (x:Int) => (y:Int) => Math.sqrt(x+y)\n", 229 | "f1(4)(16)" 230 | ] 231 | }, 232 | { 233 | "cell_type": "markdown", 234 | "metadata": {}, 235 | "source": [ 236 | "### 4. Exercise\n", 237 | "\n", 238 | "A function definition is given below.\n", 239 | "Create an equivalent function by removing all optional parts." 240 | ] 241 | }, 242 | { 243 | "cell_type": "code", 244 | "execution_count": 6, 245 | "metadata": {}, 246 | "outputs": [ 247 | { 248 | "data": { 249 | "text/plain": [ 250 | "Hi There" 251 | ] 252 | }, 253 | "execution_count": 6, 254 | "metadata": {}, 255 | "output_type": "execute_result" 256 | } 257 | ], 258 | "source": [ 259 | "val fs:String => (String => String) = (prefix: String) => {(s: String) => { prefix + \" \" + s } }\n", 260 | "fs(\"Hi\")(\"There\")" 261 | ] 262 | }, 263 | { 264 | "cell_type": "markdown", 265 | "metadata": {}, 266 | "source": [ 267 | "### 5. Exercise\n", 268 | "\n", 269 | "Can you create a function that can be called as given below.\n", 270 | "\n", 271 | "```scala\n", 272 | "fs1(\"Hi\")()\n", 273 | "\n", 274 | "Output : - Hi There\n", 275 | "```" 276 | ] 277 | }, 278 | { 279 | "cell_type": "markdown", 280 | "metadata": {}, 281 | "source": [ 282 | "### 6. Exercise\n", 283 | "\n", 284 | "Create an integer decorator function that takes an integer and also takes a function.\n", 285 | "The function converts an integer to a decorated string as given below.\n", 286 | "```scala\n", 287 | "intDecorator(5, (y:Int) => \"\" + y + \"\" )\n", 288 | "\n", 289 | "Output - 5\n", 290 | "```" 291 | ] 292 | }, 293 | { 294 | "cell_type": "markdown", 295 | "metadata": {}, 296 | "source": [ 297 | "### 7. Exercise\n", 298 | "\n", 299 | "Take the function call from *Exercise 6*." 300 | ] 301 | }, 302 | { 303 | "cell_type": "code", 304 | "execution_count": 7, 305 | "metadata": {}, 306 | "outputs": [ 307 | { 308 | "data": { 309 | "text/plain": [ 310 | "5" 311 | ] 312 | }, 313 | "execution_count": 7, 314 | "metadata": {}, 315 | "output_type": "execute_result" 316 | } 317 | ], 318 | "source": [ 319 | "intDecorator(5, (y:Int) => \"\" + y + \"\" )" 320 | ] 321 | }, 322 | { 323 | "cell_type": "markdown", 324 | "metadata": {}, 325 | "source": [ 326 | "Change this call to use a placeholder syntax." 327 | ] 328 | }, 329 | { 330 | "cell_type": "markdown", 331 | "metadata": {}, 332 | "source": [ 333 | "### 8. Exercise\n", 334 | "\n", 335 | "Create a function SumX. It should take three parameters. The first two parameters are integer. The second parameter is the logic to calculate sum of first two parameters. You should be able to use the function to calculate sum of cubes of first two parameters as shown below.\n", 336 | "```scala\n", 337 | "sumX(3,5, (x,y) => x*x*x + y*y*y )\n", 338 | "```" 339 | ] 340 | }, 341 | { 342 | "cell_type": "markdown", 343 | "metadata": {}, 344 | "source": [ 345 | "### 9. Exercise\n", 346 | "\n", 347 | "Take the function definition call for *Exercise 8*. Call it using placeholder syntax." 348 | ] 349 | }, 350 | { 351 | "cell_type": "markdown", 352 | "metadata": {}, 353 | "source": [ 354 | "### 10. Exercise\n", 355 | "\n", 356 | "Create a function *greetSomeone(prefix:String)*. It should return another function. The returned function will take another string and print a greeting message.\n", 357 | "\n", 358 | "Here is an example of using the greetSomeone.\n", 359 | "```scala\n", 360 | "val helloSomeone = greetSomeone(\"Hello\")\n", 361 | "helloSomeone(\"Prashant\")\n", 362 | "\n", 363 | "Output:- Hello Prashant\n", 364 | "```" 365 | ] 366 | }, 367 | { 368 | "cell_type": "markdown", 369 | "metadata": {}, 370 | "source": [ 371 | "

Solutions

\n", 372 | "***************************" 373 | ] 374 | }, 375 | { 376 | "cell_type": "markdown", 377 | "metadata": {}, 378 | "source": [ 379 | "### 1. Solution" 380 | ] 381 | }, 382 | { 383 | "cell_type": "markdown", 384 | "metadata": {}, 385 | "source": [ 386 | "**Using def Syntax**" 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "execution_count": 10, 392 | "metadata": { 393 | "collapsed": true 394 | }, 395 | "outputs": [], 396 | "source": [ 397 | "def f1(x:Int) = {\n", 398 | " println(s\"SQRT of $x is \" + Math.sqrt(x))\n", 399 | " (y:Int) => Math.sqrt(x+y)\n", 400 | "}" 401 | ] 402 | }, 403 | { 404 | "cell_type": "markdown", 405 | "metadata": {}, 406 | "source": [ 407 | "You can call it using below method" 408 | ] 409 | }, 410 | { 411 | "cell_type": "code", 412 | "execution_count": 11, 413 | "metadata": {}, 414 | "outputs": [ 415 | { 416 | "name": "stdout", 417 | "output_type": "stream", 418 | "text": [ 419 | "SQRT of 4 is 2.0\n" 420 | ] 421 | }, 422 | { 423 | "data": { 424 | "text/plain": [ 425 | "4.47213595499958" 426 | ] 427 | }, 428 | "execution_count": 11, 429 | "metadata": {}, 430 | "output_type": "execute_result" 431 | } 432 | ], 433 | "source": [ 434 | "val f2 = f1(4)\n", 435 | "f2(16)" 436 | ] 437 | }, 438 | { 439 | "cell_type": "markdown", 440 | "metadata": {}, 441 | "source": [ 442 | "**Using literal Syntax**" 443 | ] 444 | }, 445 | { 446 | "cell_type": "code", 447 | "execution_count": 12, 448 | "metadata": { 449 | "collapsed": true 450 | }, 451 | "outputs": [], 452 | "source": [ 453 | "val f1 = (x:Int) => {\n", 454 | " println(s\"SQRT of $x is \" + Math.sqrt(x))\n", 455 | " (y:Int) => Math.sqrt(x+y)\n", 456 | "}" 457 | ] 458 | }, 459 | { 460 | "cell_type": "markdown", 461 | "metadata": {}, 462 | "source": [ 463 | "You can call it as shown in above example. You can also call it using a chain of functions" 464 | ] 465 | }, 466 | { 467 | "cell_type": "code", 468 | "execution_count": 13, 469 | "metadata": {}, 470 | "outputs": [ 471 | { 472 | "name": "stdout", 473 | "output_type": "stream", 474 | "text": [ 475 | "SQRT of 4 is 2.0\n" 476 | ] 477 | }, 478 | { 479 | "data": { 480 | "text/plain": [ 481 | "4.47213595499958" 482 | ] 483 | }, 484 | "execution_count": 13, 485 | "metadata": {}, 486 | "output_type": "execute_result" 487 | } 488 | ], 489 | "source": [ 490 | "f1(4)(16)" 491 | ] 492 | }, 493 | { 494 | "cell_type": "markdown", 495 | "metadata": {}, 496 | "source": [ 497 | "#### Discussion" 498 | ] 499 | }, 500 | { 501 | "cell_type": "markdown", 502 | "metadata": {}, 503 | "source": [ 504 | "Both the examples are same and using the same technique to return a function. They create a local anonymous function as the last expression, and Scala will automatically return the last expression. So, if you want to return a function from a Higher Order function, all you have to do is to create an anonymous local function as the last expression." 505 | ] 506 | }, 507 | { 508 | "cell_type": "markdown", 509 | "metadata": {}, 510 | "source": [ 511 | "#### Caution" 512 | ] 513 | }, 514 | { 515 | "cell_type": "markdown", 516 | "metadata": {}, 517 | "source": [ 518 | "You must use an anonymous function. If you give it a name, it becomes an ordinary local function." 519 | ] 520 | }, 521 | { 522 | "cell_type": "markdown", 523 | "metadata": {}, 524 | "source": [ 525 | "### 2. Solution" 526 | ] 527 | }, 528 | { 529 | "cell_type": "code", 530 | "execution_count": 14, 531 | "metadata": { 532 | "collapsed": true 533 | }, 534 | "outputs": [], 535 | "source": [ 536 | "def f1(x:Int) = {\n", 537 | " println(s\"SQRT of $x is \" + Math.sqrt(x))\n", 538 | " def f2(y:Int) = Math.sqrt(x+y)\n", 539 | " f2 _\n", 540 | "}" 541 | ] 542 | }, 543 | { 544 | "cell_type": "code", 545 | "execution_count": 15, 546 | "metadata": {}, 547 | "outputs": [ 548 | { 549 | "name": "stdout", 550 | "output_type": "stream", 551 | "text": [ 552 | "SQRT of 4 is 2.0\n" 553 | ] 554 | }, 555 | { 556 | "data": { 557 | "text/plain": [ 558 | "4.47213595499958" 559 | ] 560 | }, 561 | "execution_count": 15, 562 | "metadata": {}, 563 | "output_type": "execute_result" 564 | } 565 | ], 566 | "source": [ 567 | "f1(4)(16)" 568 | ] 569 | }, 570 | { 571 | "cell_type": "markdown", 572 | "metadata": {}, 573 | "source": [ 574 | "#### Discussion" 575 | ] 576 | }, 577 | { 578 | "cell_type": "markdown", 579 | "metadata": {}, 580 | "source": [ 581 | "You can use partially applied function to return an ordinary local function." 582 | ] 583 | }, 584 | { 585 | "cell_type": "markdown", 586 | "metadata": {}, 587 | "source": [ 588 | "### 3. Solution" 589 | ] 590 | }, 591 | { 592 | "cell_type": "code", 593 | "execution_count": 18, 594 | "metadata": {}, 595 | "outputs": [ 596 | { 597 | "data": { 598 | "text/plain": [ 599 | "4.47213595499958" 600 | ] 601 | }, 602 | "execution_count": 18, 603 | "metadata": {}, 604 | "output_type": "execute_result" 605 | } 606 | ], 607 | "source": [ 608 | "val f1 = (x:Int) => (y:Int) => Math.sqrt(x+y)\n", 609 | "f1(4)(16)" 610 | ] 611 | }, 612 | { 613 | "cell_type": "markdown", 614 | "metadata": {}, 615 | "source": [ 616 | "#### Discussion" 617 | ] 618 | }, 619 | { 620 | "cell_type": "markdown", 621 | "metadata": {}, 622 | "source": [ 623 | "We can remove the value type annotation. It starts from \":\" and goes upto the \"=\" symbol." 624 | ] 625 | }, 626 | { 627 | "cell_type": "markdown", 628 | "metadata": {}, 629 | "source": [ 630 | "### 4. Solution" 631 | ] 632 | }, 633 | { 634 | "cell_type": "code", 635 | "execution_count": 20, 636 | "metadata": {}, 637 | "outputs": [ 638 | { 639 | "data": { 640 | "text/plain": [ 641 | "Hi There" 642 | ] 643 | }, 644 | "execution_count": 20, 645 | "metadata": {}, 646 | "output_type": "execute_result" 647 | } 648 | ], 649 | "source": [ 650 | "val fs = (prefix: String) => (s: String) => prefix + \" \" + s\n", 651 | "fs(\"Hi\")(\"There\")" 652 | ] 653 | }, 654 | { 655 | "cell_type": "markdown", 656 | "metadata": {}, 657 | "source": [ 658 | "### 5. Solution" 659 | ] 660 | }, 661 | { 662 | "cell_type": "code", 663 | "execution_count": 21, 664 | "metadata": {}, 665 | "outputs": [ 666 | { 667 | "data": { 668 | "text/plain": [ 669 | "Hi There" 670 | ] 671 | }, 672 | "execution_count": 21, 673 | "metadata": {}, 674 | "output_type": "execute_result" 675 | } 676 | ], 677 | "source": [ 678 | "val fs1 = (prefix: String) => { () => prefix + \" \" + \"There\" }\n", 679 | "fs1(\"Hi\")()" 680 | ] 681 | }, 682 | { 683 | "cell_type": "markdown", 684 | "metadata": {}, 685 | "source": [ 686 | "### 6. Solution" 687 | ] 688 | }, 689 | { 690 | "cell_type": "code", 691 | "execution_count": 2, 692 | "metadata": {}, 693 | "outputs": [ 694 | { 695 | "data": { 696 | "text/plain": [ 697 | "5" 698 | ] 699 | }, 700 | "execution_count": 2, 701 | "metadata": {}, 702 | "output_type": "execute_result" 703 | } 704 | ], 705 | "source": [ 706 | "def intDecorator(x:Int, f: Int => String) = f(x)\n", 707 | "intDecorator(5, (y:Int) => \"\" + y + \"\" )" 708 | ] 709 | }, 710 | { 711 | "cell_type": "markdown", 712 | "metadata": {}, 713 | "source": [ 714 | "### 7. Solution" 715 | ] 716 | }, 717 | { 718 | "cell_type": "code", 719 | "execution_count": 3, 720 | "metadata": {}, 721 | "outputs": [ 722 | { 723 | "data": { 724 | "text/plain": [ 725 | "5" 726 | ] 727 | }, 728 | "execution_count": 3, 729 | "metadata": {}, 730 | "output_type": "execute_result" 731 | } 732 | ], 733 | "source": [ 734 | "intDecorator(5, \"\" + _ + \"\" )" 735 | ] 736 | }, 737 | { 738 | "cell_type": "markdown", 739 | "metadata": {}, 740 | "source": [ 741 | "### 8. Solution" 742 | ] 743 | }, 744 | { 745 | "cell_type": "code", 746 | "execution_count": 6, 747 | "metadata": {}, 748 | "outputs": [ 749 | { 750 | "data": { 751 | "text/plain": [ 752 | "152" 753 | ] 754 | }, 755 | "execution_count": 6, 756 | "metadata": {}, 757 | "output_type": "execute_result" 758 | } 759 | ], 760 | "source": [ 761 | "def sumX(x:Int,y:Int,f: (Int,Int) => Int) = f(x,y)\n", 762 | "sumX(3,5, (x,y) => x*x*x + y*y*y )\n" 763 | ] 764 | }, 765 | { 766 | "cell_type": "markdown", 767 | "metadata": {}, 768 | "source": [ 769 | "### 9. Solution" 770 | ] 771 | }, 772 | { 773 | "cell_type": "markdown", 774 | "metadata": {}, 775 | "source": [ 776 | "We can't use placeholder syntax in this case because we will need six underscores. That will violate the rule that the number of input parameters must be equal to the number of underscores." 777 | ] 778 | }, 779 | { 780 | "cell_type": "markdown", 781 | "metadata": {}, 782 | "source": [ 783 | "### 10. Solution" 784 | ] 785 | }, 786 | { 787 | "cell_type": "code", 788 | "execution_count": 17, 789 | "metadata": {}, 790 | "outputs": [ 791 | { 792 | "name": "stdout", 793 | "output_type": "stream", 794 | "text": [ 795 | "Hello Prashant\n" 796 | ] 797 | } 798 | ], 799 | "source": [ 800 | "def greetSomeone(prefix:String) = (name:String) => println(prefix + \" \" + name)\n", 801 | "val helloSomeone = greetSomeone(\"Hello\")\n", 802 | "helloSomeone(\"Prashant\")" 803 | ] 804 | }, 805 | { 806 | "cell_type": "markdown", 807 | "metadata": {}, 808 | "source": [ 809 | "# What's Next\n", 810 | "\n", 811 | "1. Download this Notebook from nbviewer [NB Viewer](https://nbviewer.jupyter.org/github/LearningJournal/ScalaTutorials/blob/master/notebooks/Scala-019-Higher-OrderFunctions.ipynb)\n", 812 | "3. Get more video tutorials - [Learning Journal @ Youtube](http://www.youtube.com/learningjournalin)" 813 | ] 814 | } 815 | ], 816 | "metadata": { 817 | "kernelspec": { 818 | "display_name": "Apache Toree - Scala", 819 | "language": "scala", 820 | "name": "apache_toree_scala" 821 | }, 822 | "language_info": { 823 | "file_extension": ".scala", 824 | "name": "scala", 825 | "version": "2.11.8" 826 | } 827 | }, 828 | "nbformat": 4, 829 | "nbformat_minor": 2 830 | } 831 | -------------------------------------------------------------------------------- /notebooks/Scala-020-VarArgs-NamedArgumentsDefaultValues.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "

Scala-020 - VarArgs, Named Arguments & Default Values

\n", 8 | "\n", 9 | "This tutorial covers following concepts\n", 10 | "1. Variable length argument.\n", 11 | "2. Named arguments.\n", 12 | "3. Default values. \n", 13 | "\n", 14 | "This notebook is a companion for the Video Tutorial. \n", 15 | "\n", 16 | "A complete video compilation is available @ [Youtube](http://www.youtube.com/learningjournalin)." 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "## Variable length arguments\n", 24 | "The variable length argument allows you to indicate that the last argument of a function can take multiple values.\n", 25 | " ### Example\n", 26 | "\n", 27 | "\n", 28 | "```scala\n", 29 | "def echo(s:String*) = s foreach println\n", 30 | "```\n", 31 | "\n", 32 | "The * indicates that the argument takes multiple values. \n", 33 | "\n", 34 | "You can use it as shown below.\n", 35 | "\n", 36 | "\n", 37 | "```scala\n", 38 | "echo(\"One\",\"Two\",\"Three\")\n", 39 | "```\n", 40 | "\n", 41 | "You can pass as many arguments as you want.\n", 42 | "\n", 43 | "\n", 44 | "```scala\n", 45 | "echo(\"One\",\"Two\",\"Three\", \"Four\", \"Five\")\n", 46 | "```\n", 47 | "\n", 48 | "### Observations\n", 49 | "\n", 50 | "You should remember three important observations.\n", 51 | "\n", 52 | "1. The repeating argument must be the last argument.\n", 53 | "2. All of repeating argument values must be of same data type.\n", 54 | "3. Scala will collect all the argument values and pass them to the function body as an array. In the above example, s is an array of strings." 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "## Named arguments\n", 62 | "\n", 63 | "In Scala, while calling a function, you can use the argument name. Using the argument name allows you to change the order of the arguments. \n", 64 | "\n", 65 | "### Example\n", 66 | "Let's take a simple function definition as shown below.\n", 67 | "\n", 68 | "\n", 69 | "```scala\n", 70 | "def doSomething(f: String => Unit, s:String) = f(s)\n", 71 | "```\n", 72 | "\n", 73 | "While calling this function, you can pass the arguments in the order of definition.\n", 74 | "```scala\n", 75 | "doSomething(x => println(\"[\" + x + \"]\") , \"Hi There!\")\n", 76 | "```\n", 77 | "The first argument is a function, and the next one is a string. If you want to change the order of the parameter values, you must use the argument names. The example shown below uses the argument names.\n", 78 | "\n", 79 | "```scala\n", 80 | "doSomething(s=\"Hi There!\", f=x => println(\"[\" + x + \"]\") )\n", 81 | "```" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "## Default Values\n", 89 | "\n", 90 | "Scala allows you to assign a default value to a parameter using an equal to symbol.\n", 91 | "\n", 92 | "The below example assigns ***println*** as a default value to ***f***.\n", 93 | "\n", 94 | "\n", 95 | "```scala\n", 96 | "def doSomething(f: String => Unit=println, s:String) = f(s)\n", 97 | "```\n", 98 | "\n", 99 | "Now you can skip the value of ***f*** and pass only second argument using a named argument syntax.\n", 100 | "Scala will take ***println*** as a value for the argument f.\n", 101 | "\n", 102 | "\n", 103 | "```scala\n", 104 | "doSomething(s=\"Hi There!\")\n", 105 | "```" 106 | ] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": {}, 111 | "source": [ 112 | "

Practice Exercise

" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "### 1. Exercise \n", 120 | "\n", 121 | "Given this function definition.\n", 122 | "```scala\n", 123 | "def echo(s:String*) = s foreach println\n", 124 | "```\n", 125 | "What is the output of below code?\n", 126 | "```scala\n", 127 | "echo(\"One\",\"Two\",3, \"Four\", \"Five\")\n", 128 | "```\n", 129 | "\n", 130 | "### 2. Exercise \n", 131 | "\n", 132 | "What is the output of below code.\n", 133 | "```scala\n", 134 | "def echo(s:String*, i:Int) = s foreach println\n", 135 | "echo(\"One\",\"Two\",\"Three\", 5)\n", 136 | "```\n", 137 | "\n", 138 | "### 3. Exercise\n", 139 | "\n", 140 | "Is the below code valid? Reason your answer.\n", 141 | "```scala\n", 142 | "def echo2(s:String*, i:Int*) = s foreach println\n", 143 | "```\n", 144 | "### 4. Exercise\n", 145 | "\n", 146 | "Can we have two variable length arguments in a single function. If your answer is yes, give an example.\n", 147 | "\n", 148 | "### 5. Exercise\n", 149 | "\n", 150 | "Is the below code valid? Reason your answer.\n", 151 | "\n", 152 | "```scala\n", 153 | "def echo(s:String*) = s foreach println\n", 154 | "echo()\n", 155 | "```\n", 156 | "\n", 157 | "### 6. Exercise\n", 158 | "\n", 159 | "Take the below code.\n", 160 | "\n", 161 | "```scala\n", 162 | "def echo(s:String*) = s foreach println\n", 163 | "val cities = List(\"Bangalore\",\"London\",\"New York City\")\n", 164 | "```\n", 165 | "Write a code to pass all the elements of the cities to the ***echo*** function.\n", 166 | "\n", 167 | "\n", 168 | "### 7. Exercise\n", 169 | "\n", 170 | "What is the output of below code.\n", 171 | "\n", 172 | "```scala\n", 173 | "def echo(i:Int, s:String*) = { \n", 174 | " println(i)\n", 175 | " s foreach println\n", 176 | "}\n", 177 | "echo(3,\"Bangalore\",\"London\",\"New York City\")\n", 178 | "```\n", 179 | "\n", 180 | "### 8. Exercise\n", 181 | "\n", 182 | "Identify the problem with the below code?\n", 183 | "```scala\n", 184 | "def echo(i:Int = 3, s:String*) = { \n", 185 | " println(i)\n", 186 | " s foreach println\n", 187 | "}\n", 188 | "echo(\"Bangalore\",\"London\",\"New York City\")\n", 189 | "```\n", 190 | "\n", 191 | "### 9. Exercise\n", 192 | "\n", 193 | "Do you see any problems in the code given below? Explain your answer.\n", 194 | "\n", 195 | "```scala\n", 196 | "def printName(first: String, last: String): Unit = {\n", 197 | " println(first + \" \" + last)\n", 198 | "}\n", 199 | "\n", 200 | "printName(last = \"Pandey\", \"Prashant\")\n", 201 | "```\n", 202 | "\n", 203 | "### 10. Exercise\n", 204 | "\n", 205 | "Assume the function definition as shown below.\n", 206 | "\n", 207 | "```scala\n", 208 | "def printName(first: String = \"Prashant\", last: String = \"Pandey\"): Unit = {\n", 209 | " println(first + \" \" + last)\n", 210 | "}\n", 211 | "```\n", 212 | "\n", 213 | "What is the output of below function calls. Explain your answers.\n", 214 | "```scala\n", 215 | "1. printName()\n", 216 | "2. printName\n", 217 | "3. printName(\"John\",\"Trivolta\")\n", 218 | "4. printName(\"Trivolta\",\"John\")\n", 219 | "5. printName(last = \"Trivolta\",\"John\")\n", 220 | "6. printName(first = \"Trivolta\",\"John\")\n", 221 | "7. printName(\"John\",last = \"Trivolta\")\n", 222 | "8. printName(last = \"Trivolta\")\n", 223 | "9. printName(first = \"John\")\n", 224 | "10. printName(\"John\",null)\n", 225 | "11. printName(first = null)\n", 226 | "```" 227 | ] 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "metadata": {}, 232 | "source": [ 233 | "

Solution

" 234 | ] 235 | }, 236 | { 237 | "cell_type": "markdown", 238 | "metadata": {}, 239 | "source": [ 240 | "### 1. Solution\n", 241 | "The given code is incorrect. The variable argument ***s*** is an string so we can't pass an integer value. The correct code should be as shown below.\n", 242 | "```scala\n", 243 | "echo(\"One\",\"Two\",\"3\", \"Four\", \"Five\")\n", 244 | "```" 245 | ] 246 | }, 247 | { 248 | "cell_type": "markdown", 249 | "metadata": {}, 250 | "source": [ 251 | "### 2. Solution\n", 252 | "The given code is incorrect. The variable argument ***s*** must be the last argument." 253 | ] 254 | }, 255 | { 256 | "cell_type": "markdown", 257 | "metadata": {}, 258 | "source": [ 259 | "### 3. Solution\n", 260 | "The given code is incorrect. This code will show an error that the variable argument must be the last argument. However, you can achive the same thing using the function currying. Check the next question for an example." 261 | ] 262 | }, 263 | { 264 | "cell_type": "markdown", 265 | "metadata": {}, 266 | "source": [ 267 | "### 4. Solution\n", 268 | "Yes you can do that. However you must break your parameters in two groups and use function currying syntax.\n", 269 | "The below code shows an example.\n", 270 | "```scala\n", 271 | "def echo2(s:String*)(i:Int*) = {\n", 272 | " s foreach println\n", 273 | " i foreach println\n", 274 | "}\n", 275 | "```\n", 276 | "You can call it using below method.\n", 277 | "```scala\n", 278 | "echo2(\"Bangalore\",\"London\",\"New York City\")(1,2,3)\n", 279 | "println(\"----------------------\")\n", 280 | "echo2(\"Bangalore\",\"London\",\"New York City\")()\n", 281 | "println(\"----------------------\")\n", 282 | "echo2()(1,2,3)\n", 283 | "println(\"----------------------\")\n", 284 | "echo2()()\n", 285 | "```" 286 | ] 287 | }, 288 | { 289 | "cell_type": "markdown", 290 | "metadata": {}, 291 | "source": [ 292 | "### 5. Solution\n", 293 | "Yes, The code is valid because VarArgs can take no or multiple parameters." 294 | ] 295 | }, 296 | { 297 | "cell_type": "markdown", 298 | "metadata": {}, 299 | "source": [ 300 | "### 6. Solution\n", 301 | "\n", 302 | "Cities is a list. If you want to pass all the elements of a collection to a VarArgs parameter, You can do it as shown below.\n", 303 | "```scala\n", 304 | "echo(cities:_*)\n", 305 | "```\n", 306 | "Variable arguments are often used with `_*`. The `_*` is a hint to the compiler to pass the elements of ***cities*** to a function instead of the ***cities*** itself.\n", 307 | "The colon (:) used before _* is the type ascription. " 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "### 7. Solution\n", 315 | "The code is simple. It will print 3 and then it will print the name of three cities." 316 | ] 317 | }, 318 | { 319 | "cell_type": "markdown", 320 | "metadata": {}, 321 | "source": [ 322 | "### 8. Solution\n", 323 | "\n", 324 | "VarArgs and default values together is not allowed.\n", 325 | "\n", 326 | "You will get an error as \"a parameter section with a `*`-parameter is not allowed to have default arguments\"" 327 | ] 328 | }, 329 | { 330 | "cell_type": "markdown", 331 | "metadata": {}, 332 | "source": [ 333 | "### 9. Solution\n", 334 | "\n", 335 | "Idealy, you should not mix named arguments and positional arguments. You can mix them as long as the order of named argument is same as the positional.\n", 336 | "\n", 337 | "In this example, we swiped the order. Hence it is not allowed." 338 | ] 339 | }, 340 | { 341 | "cell_type": "markdown", 342 | "metadata": {}, 343 | "source": [ 344 | "### 10. Solution\n", 345 | "1. This call is perfect. The function call will take default values.\n", 346 | "2. This call is incorrect. Default value makes it mandatory to use parenthesis.\n", 347 | "3. This call is perfect. It is using positional parameters.\n", 348 | "4. This call is perfect. It is using positional parameters.\n", 349 | "5. This call is incorrect because it is using positional after named argument.\n", 350 | "6. This call is perfect even if it is using positional after named because the order of named argument is same as positional.\n", 351 | "7. This call is perfect even if it is using positional after named because the order of named argument is same as positional.\n", 352 | "8. This call is perfect. The first parameter takes default value and the second one is positional.\n", 353 | "9. This call is perfect. The first argument takes a positional value and the second one is a default.\n", 354 | "10. This call is perfect. Both parameters are positional.\n", 355 | "11. This call is perfect. The first parameter is named and the second one takes a default value." 356 | ] 357 | } 358 | ], 359 | "metadata": { 360 | "kernelspec": { 361 | "display_name": "Apache Toree - Scala", 362 | "language": "scala", 363 | "name": "apache_toree_scala" 364 | }, 365 | "language_info": { 366 | "file_extension": ".scala", 367 | "name": "scala", 368 | "version": "2.11.8" 369 | } 370 | }, 371 | "nbformat": 4, 372 | "nbformat_minor": 2 373 | } 374 | --------------------------------------------------------------------------------