Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • lamp/cs210
  • kgatti/cs210
  • houle/cs210
  • bbernath/cs210
  • bhle/cs210
  • boukhari/cs210
  • adda/cs210
  • bedmar/cs210
  • elacroix/cs210
  • czestoch/cs210
  • flealsan/cs210
  • karoubi/cs210
  • ullmo/cs210
  • norlha/cs210
  • kot/cs210
  • devimeux/cs210
  • malahlou/cs210
  • saucy/cs210
  • abachman/cs210
  • essonni/cs210
  • balducci/cs210
  • jfreeman/cs210
  • tgence/cs210
  • seddik/cs210
  • kahmed/cs210
25 results
Select Git revision
Show changes
Commits on Source (67)
Showing
with 12 additions and 1287 deletions
This repository will be used as the website for Functional Programming CS-210. It will be updated weekly throughout the semester. This README contains general information about the class.
# CS-210 Functional Programming
- [previous-exams](previous-exams) contains PDFs for the previous exams.
- [exercises](exercises) contains markdown documents for the exercise sessions and solutions.
- [slides](slides) contains the slides presented in class (also attached or respective videos).
- [labs](labs) contains markdown documents for the labs.
We will use GitLab's issue tracker as a discussion forum. Feel free to [open an issue](https://gitlab.epfl.ch/lamp/cs210/issues/new) if you have any comments or questions
# First-week Tasks
1. [Join the Discord](https://discord.gg/UqzqX2wTWW).
2. [Log into EPFL's GitLab](https://gitlab.epfl.ch/users/sign_in).
3. Fill in [this table](https://docs.google.com/spreadsheets/d/12KvfD_jN5AcApmWhCz7xZmln48fctQOa984RPWrqRkY/edit#gid=0) with your GASPAR and SCIPER number to initialize your GitLab repository for the course (login with your `@epfl.ch` address to have write access).
4. Choose a group for the exercises (recitation sessions) by answering [this Doodle](https://doodle.com/poll/4k7gkxiv9hdxzivk).
5. Follow the [Tools Setup](labs/tools-setup.md) page.
6. Do the [example lab](labs/example-lab.md).
7. Do the [first graded lab](labs/lab-1.md).
## Grading
The grading of the course is divided between labs (30%), a midterm exam (20%) and a final exam (50%).
## Staff
| Role | People |
| :--- | :--- |
| Professors | [Martin Odersky](https://people.epfl.ch/martin.odersky), [Viktor Kunčak](https://people.epfl.ch/viktor.kuncak) |
| TAs | [Dragana Milovancevic](https://people.epfl.ch/dragana.milovancevic), [Ergys Dona](https://people.epfl.ch/ergys.dona), [Jean-Baptiste Cordonnier](https://people.epfl.ch/jean-baptiste.cordonnier), [Matthieu Bovel](https://people.epfl.ch/matthieu.bovel) |
| Student TAs | [Joshua Bernimoulin](https://people.epfl.ch/joshua.bernimoulin), [Mohamed Yassine Boukhari](https://people.epfl.ch/mohamed.boukhari), [Hind El Bouchrifi ](https://people.epfl.ch/hind.elbouchrifi), [Luca Giordano](https://people.epfl.ch/lucas.giordano), [Mohamed Hichem Hadhri](https://people.epfl.ch/mohamed.hadhri), [Salim Najib](https://people.epfl.ch/salim.najib), [Arthur Vignon](https://people.epfl.ch/arthur.vignon) |
## Lecture Schedule
<!-- date -d "30/09/2019 364 days" +"%d.%m.%Y" -->
Lectures are prerecorded and published below. This class is given in a [_flipped classrom_](https://en.wikipedia.org/wiki/Flipped_classroom) format, meaning that you should watch the videos by yourself _before_ the indicated date. You will then have the occasion to test and perfect your knowledge during the [exercises (recitation sessions)](#user-content-exercise-recitation-session-schedule) on Wednesday afternoons, and [labs](#user-content-lab-schedule) on Friday mornings.
**Note**: In some lectures, worksheets are used to present code. To learn how to
use worksheets yourselves, please follow the [Tools
Setup](labs/tools-setup.md) and [example lab](labs/example-lab.md). To create a
new empty project to experiment with worksheets, you can clone the following
repository and run `code . ` inside as usual: [`git clone https://gitlab.epfl.ch/lamp/cs210-worksheets`](https://gitlab.epfl.ch/lamp/cs210-worksheets)
| Week | Date | Topic | Videos & Slides |
| :-- | :-- | :-- | :-- |
| 1 | 22.09.2021 | Intro class | Introduction ([Video][Video 1.1.1], [Slides][Slides 1.1.1])<br/>Elements of programming ([Video][Video 1.1.2], [Slides][Slides 1.1.2])<br/>Evaluation strategies and termination ([Video][Video 1.1.3], [Slides][Slides 1.1.3])<br/>Value Definitions and Conditionals ([Video][Video 1.1.4], [Slides][Slides 1.1.4])<br/>Square Roots with Newtons Methods ([Video][Video 1.1.5], [Slides][Slides 1.1.5])<br/>Blocks and lexical scopes ([Video][Video 1.1.6], [Slides][Slides 1.1.6])<br/>Tail Recursion ([Video][Video 1.1.7], [Slides][Slides 1.1.7]) |
| 2 | 29.09.2021 | Recursion / Function values | Higher-Order Functions ([Video][Video 1.2.1], [Slides][Slides 1.2.1])<br/>Currying ([Video][Video 1.2.2], [Slides][Slides 1.2.2])<br/>Finding FixedPoints ([Video][Video 1.2.3], [Slides][Slides 1.2.3])<br/>Scala Syntax Summary ([Video][Video 1.2.4], [Slides][Slides 1.2.4])<br/>Functions and Data ([Video][Video 1.2.5], [Slides][Slides 1.2.5])<br/>Data Abstraction ([Video][Video 1.2.6], [Slides][Slides 1.2.6])<br/>Evaluation and Operators ([Video][Video 1.2.7], [Slides][Slides 1.2.7]) |
| 3 | 06.10.2021 | Classes | Class Hierarchies ([Video][Video 1.3.1], [Slides][Slides 1.3.1])<br/>How Classes are Organized ([Video][Video 1.3.2], [Slides][Slides 1.3.2])<br/>Polymorphism ([Video][Video 1.3.3], [Slides][Slides 1.3.3])<br/>Objects Everywhere ([Video][Video 1.3.4], [Slides][Slides 1.3.4])<br/>Functions as Objects ([Video][Video 1.3.5], [Slides][Slides 1.3.5]) |
| 4 | 13.10.2021 | Classes | Decomposition ([Video][Video 1.4.1], [Slides][Slides 1.4.1])<br/>Pattern Matching ([Video][Video 1.4.2], [Slides][Slides 1.4.2])<br/>Lists ([Video][Video 1.4.3], [Slides][Slides 1.4.3])<br/>Enums ([Video][Video 1.4.4], [Slides][Slides 1.4.4])<br/>Subtyping and Generics ([Video][Video 1.4.5], [Slides][Slides 1.4.5])<br/>Variance ([Video][Video 1.4.6], [Slides][Slides 1.4.6]) |
| 5 | 20.10.2021 | List | A closer look at lists ([Video][Video 1.5.1], [Slides][Slides 1.5.1])<br/>Tuples and generic methods ([Video][Video 1.5.2], [Slides][Slides 1.5.2])<br/>Higher order list functions ([Video][Video 1.5.3], [Slides][Slides 1.5.3])<br/>Reduction of lists ([Video][Video 1.5.4], [Slides][Slides 1.5.4])<br/>Reasoning about lists ([Video][Video 1.5.5], [Slides][Slides 1.5.5]) |
| 6 | 27.10.2021 | Collection | Other Collections ([Video][Video 1.6.1], [Slides][Slides 1.6.1])<br/>Combinatorial Search and For-Expressions ([Video][Video 1.6.2], [Slides][Slides 1.6.2])<br/>Combinatorial Search Example ([Video][Video 1.6.3], [Slides][Slides 1.6.3])<br/>Maps ([Video][Video 1.6.4], [Slides][Slides 1.6.4])<br/>Putting the Pieces Together ([Video][Video 1.6.5], [Slides][Slides 1.6.5]) |
| 7 | 03.11.2021 | Monads | Recap ([Video][Video 2.1.1], [Slides][Slides 2.1.1])<br/>Queries with for ([Video][Video 2.1.2], [Slides][Slides 2.1.2])<br/>Translation of for ([Video][Video 2.1.3], [Slides][Slides 2.1.3])<br/>Functional Random Generators ([Video][Video 2.1.4], [Slides][Slides 2.1.4])<br/>Monads ([Video][Video 2.1.5], [Slides][Slides 2.1.5])<br/>Exceptional Monads ([Video][Video 2.1.6], [Slides][Slides 2.1.6]) |
| 8 | 10.11.2021 | **Midterm exam** | - |
| 9 | 17.11.2021 | Lazy evaluation | Structural Induction on Trees ([Video][Video 2.2.1], [Slides][Slides 2.2.1])<br/>Lazy Lists ([Video][Video 2.2.2], [Slides][Slides 2.2.2])<br/>Lazy Evaluation ([Video][Video 2.2.3], [Slides][Slides 2.2.3])<br/>Infinite Sequences ([Video][Video 2.2.4], [Slides][Slides 2.2.4])<br/>Case Study ([Video][Video 2.2.5], [Slides][Slides 2.2.5]) |
| 10 | 24.11.2021 | Type-directed computation | Contextual abstraction ([Video][Video 2.3.1], [Slides][Slides 2.3.1])<br/>Using clauses and given instances ([Video][Video 2.3.2], [Slides][Slides 2.3.2])<br/>Type classes ([Video][Video 2.3.3], [Slides][Slides 2.3.3])<br/>Abstract algebra and type classes ([Video][Video 2.3.4], [Slides][Slides 2.3.4])<br/>Context passing ([Video][Video 2.3.5], [Slides][Slides 2.3.5])<br/>Implicit function types ([Video][Video 2.3.6], [Slides][Slides 2.3.6]) |
| 11 | 01.12.2021 | State | Functions and state ([Video][Video 2.4.1], [Slides][Slides 2.4.1])<br/>Identity and change ([Video][Video 2.4.2], [Slides][Slides 2.4.2])<br/>Loops ([Video][Video 2.4.3], [Slides][Slides 2.4.3])<br/>Discrete Event Simulation ([Video][Video 2.4.4], [Slides][Slides 2.4.4]) |
| 12 | 08.12.2021 | Interpreter I | Interpreter for Arithmetic ([Video][Video 3.1.1], [Slides][Slides 3.1.1])<br/>Substitution Interpreter for Recursive Functions ([Video][Video 3.1.2], [Slides][Slides 3.1.2])<br/>Environment Instead of Substitutions ([Video][Video 3.1.3], [Slides][Slides 3.1.3])<br/>Higher-Order Functions Using Naive Substitutions ([Video][Video 3.1.4], [Slides][Slides 3.1.4])<br/>Avoiding Variable Capture ([Video][Video 3.1.5], [Slides][Slides 3.1.5])<br/>Higher-Order Functions Using Environments ([Video][Video 3.1.6], [Slides][Slides 3.1.6])<br/>Nested Recursive Definitions ([Video][Video 3.1.7], [Slides][Slides 3.1.7]) |
| 13 | 15.12.2021 | Parsing with Combinators / Lambda Calculus | Parsing with Combinators ([Video][Video 3.2.1])<br/>Recursion as Self-Application ([Video][Video 3.2.2])<br/>Church Numerals and Conditionals ([Video][Video 3.2.3]) |
| 14 | 22.12.2021 | **Final exam** | - |
## Exercise (Recitation Session) Schedule
Exercises (aka recitation sessions) take place on Wednesdays from 13:15 to 15:00 in CO1, CO015, CO016, CO017, DIA004 and DIA005. Please go to the room that you registered to on Doodle. If you have forgotten which room you chose, please ask a TA on Discord (we cannot publish the whole list for privacy reasons).
| Title | Handout Released | Session (Wednesdays 13:15 to 15:00) | Solution Released |
| :-- | :-- | :-- | :-- |
| First week tasks | - | 22.09.2021 | - |
| Exercise Session 1 | 27.09.2021 | 29.09.2021 | 04.10.2021 |
| Exercise Session 2 | 04.10.2021 | 06.10.2021 | 11.10.2021 |
| Exercise Session 3 | 11.10.2021 | 13.10.2021 | 18.10.2021 |
| Exercise Session 4 | 18.10.2021 | 20.10.2021 | 25.10.2021 |
| Exercise Session 5 | 25.10.2021 | 27.10.2021 | 01.11.2021 |
| Exercise Session 6 | 01.11.2021 | 03.11.2021 | 08.11.2021 |
| **Midterm exam** | - | 10.11.2021 | - |
| Exercise Session 7 | 15.11.2021 | 17.11.2021 | 22.11.2021 |
| Exercise Session 8 | 22.11.2021 | 24.11.2021 | 29.11.2021 |
| Exercise Session 9 | 29.11.2021 | 01.12.2021 & 08.12.2021 | 13.12.2021 |
| Exercise Session 10 | 06.12.2021 | 08.12.2021 & 15.12.2021 | 20.12.2021 |
| **Final exam** | - | 22.12.2021 | - |
Exercises are pen and paper style questions that will prepare you for the final exam.
Exercises should be done in groups.
## Lab Schedule
Lab sessions take place on Fridays from 10:15 to 12:00 in CO021, ELA1, ELD120, DIA005 and DIA004.
| Title | Start Date | Session (Fridays 10:15 to 12:00) | Due Date ([AoE](https://en.wikipedia.org/wiki/Anywhere_on_Earth)) |
| :-- | :-- | :-- | :-- |
| Recursion | 22.09.2021 | 24.09.2021 | 03.10.2021 |
| Functional Sets | 29.09.2021 | 01.10.2021 | 07.10.2021 |
| Object-Oriented Sets | 06.10.2021 | 08.10.2021 | 14.10.2021 |
| Huffman Coding | 13.10.2021 | 15.10.2021 & 22.10.2021 | 28.10.2021 |
| Anagrams | 27.10.2021 | 29.10.2021 | 11.11.2021 |
| Quickcheck | 03.11.2021 | 05.11.2021 | 18.11.2021 |
| Bloxorz | 10.11.2021 | 12.11.2021 & 19.11.2021 | 25.11.2021 |
| Codecs | 24.11.2021 | 26.11.2021 & 03.12.2021 | 09.12.2021 |
| Interpreter | 08.12.2021 | 10.12.2021 & 17.12.2021 | 23.12.2021 |
Labs are individual assignments where you get to write Scala programs using the concepts learned during lectures.
Labs are submitted by pushing your code on GitLab, see details in the [grading and submission](labs/grading-and-submission.md) page.
## Exam Schedule
The midterm exam will be on 10.11.2021.
The final exam will be on 22.12.2021.
Information about exam organization will be communicated by email a few days before the exam.
[Video 1.1.1]: https://tube.switch.ch/videos/7ed71e65
[Video 1.1.2]: https://tube.switch.ch/videos/eefaaa33
[Video 1.1.3]: https://tube.switch.ch/videos/7ec55c9c
[Video 1.1.4]: https://tube.switch.ch/videos/f8abe6bf
[Video 1.1.5]: https://tube.switch.ch/videos/1f8d3205
[Video 1.1.6]: https://tube.switch.ch/videos/9274e0f4
[Video 1.1.7]: https://tube.switch.ch/videos/1843caa3
[Slides 1.1.1]: ./slides/progfun1-1-1.pdf
[Slides 1.1.2]: ./slides/progfun1-1-2.pdf
[Slides 1.1.3]: ./slides/progfun1-1-3.pdf
[Slides 1.1.4]: ./slides/progfun1-1-4.pdf
[Slides 1.1.5]: ./slides/progfun1-1-5.pdf
[Slides 1.1.6]: ./slides/progfun1-1-6.pdf
[Slides 1.1.7]: ./slides/progfun1-1-7.pdf
[Video 1.2.1]: https://tube.switch.ch/videos/646cfe4f
[Video 1.2.2]: https://tube.switch.ch/videos/9e573d2f
[Video 1.2.3]: https://tube.switch.ch/videos/0e2be793
[Video 1.2.4]: https://tube.switch.ch/videos/ddcbb43f
[Video 1.2.5]: https://tube.switch.ch/videos/dec623bc
[Video 1.2.6]: https://tube.switch.ch/videos/6e8643cf
[Video 1.2.7]: https://tube.switch.ch/videos/p6uOZxpZO0
[Slides 1.2.1]: ./slides/progfun1-2-1.pdf
[Slides 1.2.2]: ./slides/progfun1-2-2.pdf
[Slides 1.2.3]: ./slides/progfun1-2-3.pdf
[Slides 1.2.4]: ./slides/progfun1-2-4.pdf
[Slides 1.2.5]: ./slides/progfun1-2-5.pdf
[Slides 1.2.6]: ./slides/progfun1-2-6.pdf
[Slides 1.2.7]: ./slides/progfun1-2-7.pdf
[Video 1.3.1]: https://tube.switch.ch/videos/56c88e00
[Video 1.3.2]: https://tube.switch.ch/videos/1c969056
[Video 1.3.3]: https://tube.switch.ch/videos/PE4EZHTXL1
[Video 1.3.4]: https://tube.switch.ch/videos/9081e1da
[Video 1.3.5]: https://tube.switch.ch/videos/e409b899
[Slides 1.3.1]: ./slides/progfun1-3-1.pdf
[Slides 1.3.2]: ./slides/progfun1-3-2.pdf
[Slides 1.3.3]: ./slides/progfun1-3-3.pdf
[Slides 1.3.4]: ./slides/progfun1-3-4.pdf
[Slides 1.3.5]: ./slides/progfun1-3-5.pdf
[Video 1.4.1]: https://tube.switch.ch/videos/f5879da4
[Video 1.4.2]: https://tube.switch.ch/videos/e7df77e5
[Video 1.4.3]: https://tube.switch.ch/videos/978832a8
[Video 1.4.4]: https://tube.switch.ch/videos/xmEdj2V0Xh
[Video 1.4.5]: https://tube.switch.ch/videos/9a844297
[Video 1.4.6]: https://tube.switch.ch/videos/35c4e417
[Slides 1.4.1]: ./slides/progfun1-4-1.pdf
[Slides 1.4.2]: ./slides/progfun1-4-2.pdf
[Slides 1.4.3]: ./slides/progfun1-4-3.pdf
[Slides 1.4.4]: ./slides/progfun1-4-4.pdf
[Slides 1.4.5]: ./slides/progfun1-4-5.pdf
[Slides 1.4.6]: ./slides/progfun1-4-6.pdf
[Video 1.5.1]: https://tube.switch.ch/videos/8e9cf6a5
[Video 1.5.2]: https://tube.switch.ch/videos/40edd184
[Video 1.5.3]: https://tube.switch.ch/videos/af626839
[Video 1.5.4]: https://tube.switch.ch/videos/e0e380fe
[Video 1.5.5]: https://tube.switch.ch/videos/9ebad679
[Slides 1.5.1]: ./slides/progfun1-5-1.pdf
[Slides 1.5.2]: ./slides/progfun1-5-2.pdf
[Slides 1.5.3]: ./slides/progfun1-5-3.pdf
[Slides 1.5.4]: ./slides/progfun1-5-4.pdf
[Slides 1.5.5]: ./slides/progfun1-5-5.pdf
[Video 1.6.1]: https://tube.switch.ch/videos/58a6fe2a
[Video 1.6.2]: https://tube.switch.ch/videos/a09a7679
[Video 1.6.3]: https://tube.switch.ch/videos/7f2fcf99
[Video 1.6.4]: https://tube.switch.ch/videos/a4519732
[Video 1.6.5]: https://tube.switch.ch/videos/30005570
[Slides 1.6.1]: ./slides/progfun1-6-1.pdf
[Slides 1.6.2]: ./slides/progfun1-6-2.pdf
[Slides 1.6.3]: ./slides/progfun1-6-3.pdf
[Slides 1.6.4]: ./slides/progfun1-6-4.pdf
[Slides 1.6.5]: ./slides/progfun1-6-5.pdf
[Slides 1.6.6]: ./slides/progfun1-6-6.pdf
[Video 2.1.1]: https://tube.switch.ch/videos/680a1d2a
[Video 2.1.2]: https://tube.switch.ch/videos/935b0da5
[Video 2.1.3]: https://tube.switch.ch/videos/2ac4c232
[Video 2.1.4]: https://tube.switch.ch/videos/f9c5677b
[Video 2.1.5]: https://tube.switch.ch/videos/DJmNHpUHba
[Video 2.1.6]: https://tube.switch.ch/videos/fdfb0609
[Slides 2.1.1]: ./slides/progfun2-1-1.pdf
[Slides 2.1.2]: ./slides/progfun2-1-2.pdf
[Slides 2.1.3]: ./slides/progfun2-1-3.pdf
[Slides 2.1.4]: ./slides/progfun2-1-4.pdf
[Slides 2.1.5]: ./slides/progfun2-1-5.pdf
[Slides 2.1.6]: ./slides/progfun2-1-6.pdf
[Video 2.2.1]: https://tube.switch.ch/videos/0accfa13
[Video 2.2.2]: https://tube.switch.ch/videos/fbd7e361
[Video 2.2.3]: https://tube.switch.ch/videos/8506774b
[Video 2.2.4]: https://tube.switch.ch/videos/7064a6b1
[Video 2.2.5]: https://tube.switch.ch/videos/889a5305
[Slides 2.2.1]: ./slides/progfun2-2-1.pdf
[Slides 2.2.2]: ./slides/progfun2-2-2.pdf
[Slides 2.2.3]: ./slides/progfun2-2-3.pdf
[Slides 2.2.4]: ./slides/progfun2-2-4.pdf
[Slides 2.2.5]: ./slides/progfun2-2-5.pdf
[Video 2.3.1]: https://tube.switch.ch/videos/d5df9a21
[Video 2.3.2]: https://tube.switch.ch/videos/xRHmz1nTpz
[Video 2.3.3]: https://tube.switch.ch/videos/XNgbIOT2Yb
[Video 2.3.4]: https://tube.switch.ch/videos/FnmJTs1Vqu
[Video 2.3.5]: https://tube.switch.ch/videos/pWXI0T9FtX
[Video 2.3.6]: https://tube.switch.ch/videos/NKZ0IVR9Yi
[Slides 2.3.1]: ./slides/progfun2-3-1.pdf
[Slides 2.3.2]: ./slides/progfun2-3-2.pdf
[Slides 2.3.3]: ./slides/progfun2-3-3.pdf
[Slides 2.3.4]: ./slides/progfun2-3-4.pdf
[Slides 2.3.5]: ./slides/progfun2-3-5.pdf
[Slides 2.3.6]: ./slides/progfun2-3-6.pdf
[Video 2.4.1]: https://tube.switch.ch/videos/f32bc013
[Video 2.4.2]: https://tube.switch.ch/videos/7bf009ce
[Video 2.4.3]: https://tube.switch.ch/videos/zEyrIXFFPV
[Video 2.4.4]: https://tube.switch.ch/videos/CvuKzoNjRg
[Slides 2.4.1]: ./slides/progfun2-4-1.pdf
[Slides 2.4.2]: ./slides/progfun2-4-2.pdf
[Slides 2.4.3]: ./slides/progfun2-4-3.pdf
[Slides 2.4.4]: ./slides/progfun2-4-4.pdf
[Video 2.5.1]: https://tube.switch.ch/videos/5ca69d05
[Video 2.5.2]: https://tube.switch.ch/videos/700fc8b5
[Video 2.5.3]: https://tube.switch.ch/videos/d93a3d12
[Slides 2.5.1]: ./slides/progfun2-5-1.pdf
[Slides 2.5.2]: ./slides/progfun2-5-2.pdf
[Slides 2.5.3]: ./slides/progfun2-5-3.pdf
[Video 3.1.1]: https://tube.switch.ch/videos/b053ad9d
[Video 3.1.2]: https://tube.switch.ch/videos/59b7ae00
[Video 3.1.3]: https://tube.switch.ch/videos/0ccb68d7
[Video 3.1.4]: https://tube.switch.ch/videos/0de70fa1
[Video 3.1.5]: https://tube.switch.ch/videos/94bc1565
[Video 3.1.6]: https://tube.switch.ch/videos/6d332501
[Video 3.1.7]: https://tube.switch.ch/videos/18ba7117
[Slides 3.1.1]: ./slides/progfun3-1-1.pdf
[Slides 3.1.2]: ./slides/progfun3-1-2.pdf
[Slides 3.1.3]: ./slides/progfun3-1-3.pdf
[Slides 3.1.4]: ./slides/progfun3-1-4.pdf
[Slides 3.1.5]: ./slides/progfun3-1-5.pdf
[Slides 3.1.6]: ./slides/progfun3-1-6.pdf
[Slides 3.1.7]: ./slides/progfun3-1-7.pdf
[Video 3.2.1]: https://tube.switch.ch/videos/d08dd17f
[Video 3.2.2]: https://tube.switch.ch/videos/17841152
[Video 3.2.3]: https://tube.switch.ch/videos/f203e6a9
[Slides 3.2.1]: ./slides/progfun3-2-1.pdf
[Slides 3.2.2]: ./slides/progfun3-2-2.pdf
[Slides 3.2.3]: ./slides/progfun3-2-3.pdf
The material for the course CS-210 Functional Programming has moved to [Moodle](https://moodle.epfl.ch/course/view.php?id=14257).
# Exercise Session 1
We will work on tail recursion in this session.
## Question 1: Factorial
Recall the factorial function that you saw in class
```scala
def factorial(n: Int): Int = if (n <= 0) 1 else n * factorial(n - 1)
```
Define a tail recursive version of it
```scala
def factorial(n: Int): Int = fact(n, 1)
@tailrec
def fact(n: Int, acc: Int): Int = ???
```
What would be the advantage of making `fact` an inner function to `factorial`?
## Question 2: Sum of elements on a list
Define a function that takes a list of integers and sums them. You can use the functions `head`, `tail`, and `isEmpty` on lists, as you have seen for your homework.
```scala
def sumList(ls: List[Int]): Int = ???
```
Convert your definition into a tail-recursive one.
## Question 3: Fast exponentiation
Fast exponentiation is a technique to optimize the exponentiation of numbers:
```
b²ⁿ = (b²)ⁿ = (bⁿ)²
b²ⁿ⁺¹ = b * b²ⁿ
```
Define a function that implements this fast exponentiation. Can you define a tail recursive version as well?
```scala
def fastExp(base: Int, exp: Int): Int = ???
```
## Question 4: Tail recursive Fibonacci
Define a function that computes the nth Fibonacci number. Can you define a tail recursive version as well? The Fibonacci recurrence is given as follows:
```
fib(n) = 1 | n = 0, 1
fib(n) = fib(n - 1) + fib(n - 2) | otherwise
```
```scala
def fibonacci(n: Int): Int = ???
```
# Exercise Session 2
This week we will work on playing with functions as values.
## Question 1.
Define the function `flip`. It takes a function and returns the same function, but with the arguments flipped.
```scala
def flip(f: (Int, Double) => Int): (Double, Int) => Int = ???
```
## Question 2.1
Define the identity function for integers, which, given an `Int`, returns it.
```scala
val id: Int => Int = ???
```
## Question 2.2
Define the compose function, that, given 2 functions `f`, `g`, returns a function that composes them, i.e., `f ∘ g`.
```scala
def compose(f: Int => Int, g: Int => Int): Int => Int = ???
```
What does `compose(id, f)(k)` evaluate to, for some function `f` and integer `k`?
## Question 2.3
Define the function `repeated`, which takes a function and repeatedly applies it `n` times (`n ≥ 0`).
```scala
def repeated(f: Int => Int, n: Int): Int => Int = ???
```
_Hint_: What values should be returned by `repeated(x => x + 1, 0)` and `repeated(x => x + 1, 3)`?
## Question 3.1
Define the function `curry2`, that curries a two arguments function. That is, `curry2(f) = g` such that `f(x, y) == (g(x))(y)`
```scala
def curry2(f: (Double, Int) => Boolean): Double => (Int => Boolean) = ???
```
_Hint_: what should `curry2((x, y) => x < y)(1.0)` return?
## Question 3.2
Define the function `uncurry2`. It takes a curried function, and creates a two-argument function.
```scala
def uncurry2(f: Double => Int => Boolean): (Double, Int) => Boolean = ???
```
## Question 4.
Write a function `fixedPoint` with the following signature:
```scala
def fixedPoint(f: Int => Int): Int => Int
```
The function takes a function `f` and returns a function that maps an integer into the fixed point of f that is obtained by iterating `f` some finite number of times starting from the initial value.
A value `x` is a fixed point of `f` if `f(x) == x`.
For each of the following expressions, indicate whether it terminates, and if so, what is the value returned:
- `fixedPoint(x => x/2)(4)`
- `fixedPoint(id)(123456)`
- `fixedPoint(x => x + 1)(0)`
- `fixedPoint(x => if (x % 10 == 0) x else x + 1)(35)`
- `fixedPoint((x: Int) => x / 2 + 5)(20)`
## Question 5.1
Write the `sum` function with the following signature:
```scala
def sum(a: Int, b: Int)(f: Int => Int): Int = ???
```
Which returns the sum of `f(i)` where `i` ranges from `a` to `b`.
_Bonus point_: Can your implementation be tail recursive ?
## Question 5.2
Write the `quadratic` function with the following signature:
```scala
def quadratic(c: Int): Int => Int = ???
```
Which returns a function that takes an integer `x` as argument and returns `(x - c)²`.
## Question 5.3
Using the above functions, define the function `quad3Integrate` which, given two integers `a` and `b`, computes the sum of `(i - 3)²` where `i` ranges from `a` to `b - 1`.
```scala
def quad3Integrate(a: Int, b: Int): Int = ???
val quad3Integrate: (Int, Int) => Int = ???
```
# Exercise Session 3
This week we will play with genericity and object-oriented programming concepts.
A [_binary search_](https://en.wikipedia.org/wiki/Binary_search_tree) tree is a binary tree such that, for a node, all elements in the left sub-tree are smaller than the element at the node, and all elements in the right sub-tree are greater than the element at the node. Therefore, binary search trees do not contain duplicate elements.
Because we want to build a generic tree structure, we also need the notion of a comparator, or a less-than-or-equal operator (denoted `leq`) for two generic elements which satisfies the following properties:
- Transitivity: `leq(a, b) && leq(b, c) => leq(a, c)`.
- Reflexivity: `leq(a, a)` is `true`.
- Anti-symmetry: `leq(a, b) && leq(b, a) => a == b`.
- Totality: either `leq(a, b)` or `leq(b, a)` is `true` (or both).
Note that the above defines a [_total order_](https://en.wikipedia.org/wiki/Total_order).
Here is the structure we will be using for implementing these trees:
```scala
trait Tree[T]
case class EmptyTree[T](leq: (T, T) => Boolean) extends Tree[T]
case class Node[T](left: Tree[T], elem: T, right: Tree[T], leq: (T, T) => Boolean) extends Tree[T]
```
For consistency, all subtrees must contain the same leq parameter.
Creating an empty binary tree for integers can be then done as follows:
```scala
val intLeq: (Int, Int) => Boolean = (x, y) => x <= y
val emptyIntTree: Tree[Int] = new EmptyTree(intLeq)
```
## Question 1
Given only `leq` for comparison, how can you test for equality? How about strictly-less-than?
## Question 2
Define the size method on `Tree[T]`, which returns its size, i.e. the number of Nodes in the tree.
```scala
def size: Int
```
Implement it in two ways:
1. within `Tree[T]`, using pattern matching,
2. in the subclasses of `Tree[T]`.
## Question 3
Define the `add` method, that adds an element to a `Tree[T]`, and returns the resulting tree:
```scala
def add(t: T): Tree[T] = ???
```
Remember that trees do not have duplicate values. If t is already in the tree, the result should be unchanged.
## Question 4
Define the function `toList`, which returns the sorted list representation for a tree. For example, `emptyIntTree.add(2).add(1).add(3).toList` should return `List(1, 2, 3)`
```scala
def toList: List[T] = ???
```
You can use the `Nil` operator for creating an empty list, and the `::` operator for adding a new element to the head of a list: `1 :: List(2, 3) == List(1, 2, 3)`. You are naturally free to define any auxiliary functions as necessary.
## Question 5
Define the function `sortedList`, which takes an unsorted list where no two elements are equal, and returns a new list that contains all the elements of the previous list (and only those), in increasing order.
```scala
def sortedList[T](leq: (T, T) => Boolean, ls: List[T]): List[T] = ???
```
_Hint_: you might need to define some auxiliary functions.
## Question 6
If all methods are implemented using pattern matching (i.e. there are no methods implemented in subclasses), can you represent your tree type as an _ADT_ (algebraic data type) using the `enum` syntax?
\ No newline at end of file
# Exercise Session 4
Variance and Pattern Matching
This week, we will work on the idea of variance, and on pattern matching. Recall that
- Lists are covariant in their only type parameter.
- Functions are contravariant in the argument, and covariant in the result.
## Question 1
Consider the following hierarchies:
```scala
abstract class Fruit
class Banana extends Fruit
class Apple extends Fruit
abstract class Liquid
class Juice extends Liquid
```
Consider also the following typing relationships for `A`, `B`, `C`, `D`: `A <: B` and `C <: D`.
Fill in the subtyping relation between the types below. Bear in mind that it might be that neither type is a subtype of the other.
| Left hand side | ?: | Right hand side |
| ---: | --- | :--- |
| List[Banana] | | List[Fruit] |
| List[A] | | List[B] |
| Banana => Juice | | Fruit => Juice |
| Banana => Juice | | Banana => Liquid |
| A => C | | B => D |
| List[Banana => Liquid] | | List[Fruit => Juice] |
| List[A => D] | | List[B => C] |
| (Fruit => Juice) => Liquid | | (Banana => Liquid) => Liquid |
| (B => C) => D | | (A => D) => D |
| Fruit => (Juice => Liquid) | | Banana => (Liquid => Liquid) |
| B => (C => D) | | A => (D => D) |
## Question 2
The following data types represent simple arithmetic expressions:
```scala
abstract class Expr
case class Number(x: Int) extends Expr
case class Var(name: String) extends Expr
case class Sum(e1: Expr, e2: Expr) extends Expr
case class Prod(e1: Expr, e2: Expr) extends Expr
```
Define a function `deriv(expr: Expr, v: String): Expr` returning the expression that is the partial derivative of `expr` with respect to the variable `v`.
```scala
def deriv(expr: Expr, v: String): Expr = ???
```
Here's an example run of the function:
```scala
> deriv(Sum(Prod(Var("x"), Var("x")), Var("y")), "x")
Sum(Sum(Prod(Var("x"), Number(1)), Prod(Number(1), Var("x"))), Number(0))
```
## Question 3
Write an expression simplifier that applies some arithmetic simplifications to an expression. For example, it would turn the above monstrous result into the following expression:
```scala
Prod(Var("x"), Number(2))
```
# Exercise Session 1, Solutions
## Question 1: Factorial
```scala
import scala.annotation.tailrec
def factorial(n: Int) =
require(n >= 0)
@tailrec
def loop(n: Int, acc: Int): Int =
if n == 0 then acc
else loop(n - 1, acc * n)
loop(n, 1)
```
## Question 2: Sum of elements on a list
```scala
import scala.annotation.tailrec
def sumList(ls: List[Int]) =
@tailrec
def loop(ls: List[Int], acc: Int): Int =
if ls.isEmpty then acc
else loop(ls.tail, acc + ls.head)
loop(ls, 0)
```
## Question 3: Fast exponentiation
```scala
import scala.annotation.tailrec
def fastExp(base: Int, exp: Int): Int =
require(exp >= 0)
@tailrec
def loop(base: Int, exp: Int, acc: Int): Int =
if exp == 0 then
acc
else if (exp % 2) != 0 then
loop(base, exp - 1, base * acc)
else
loop(base * base, exp / 2, acc)
loop(base, exp, 1)
```
## Question 4: Tail recursive Fibonacci
```scala
import scala.annotation.tailrec
def fibonacci(n: Int): Int =
require(n >= 0)
@tailrec
def loop(k: Int, previous: Int, current: Int): Int =
if k == n then current
else loop(k + 1, current, previous + current)
if n == 0 then 0 else loop(1, 0, 1)
```
# Exercise Session 2, Solutions
## Question 1
```scala
def flip(f: (Double, Int) => Boolean): (Int, Double) => Boolean =
(x1: Int, x2: Double) => f(x2, x1)
```
## Question 2
### Question 2.1
```scala
val id: Int => Int = (x: Int) => x
```
### Question 2.2
```scala
def compose(f: Int => Int, g: Int => Int): Int => Int =
(x: Int) => f(g(x))
```
`compose(id, f)(k)` evaluates to `f(k)`, as does `compose(f, id)(k)`.
More generally (see ["Identity Function" on Wikipedia](https://en.wikipedia.org/wiki/Identity_function#Algebraic_properties)):
> If f: M → N is any function, then we have f ∘ id<sub>M</sub> = f = id<sub>N</sub> ∘ f.
### Question 2.3
```scala
def repeated(f: Int => Int, n: Int): Int => Int =
if n == 0 then identity
else compose(f, repeated(f, n-1))
```
## Question 3
### Question 3.1
```scala
def curry2(f: (Double, Int) => Boolean): Double => (Int => Boolean) =
(x1: Double) => (x2: Int) => f(x1, x2)
```
### Question 3.2
```scala
def uncurry2(f: Double => Int => Boolean): (Double, Int) => Boolean =
(x1: Double, x2: Int) => f(x1)(x2)
```
## Question 4
```scala
import scala.annotation.tailrec
def fixedPoint(f: Int => Int): Int => Int =
@tailrec
def loop(guess: Int): Int =
val image: Int = f(guess)
if image == guess then guess else loop(image)
loop
```
Or alternatively, using currying:
```scala
def fixedPointCurry(f: Int => Int)(guess: Int): Int =
val image: Int = f(guess)
if image == guess then guess else fixedPoint(f)(image)
```
- `fixedPoint(x => x/2)(4)` returns `0`.
- `fixedPoint(id)(123456)` returns `123456`.
- `fixedPoint(x => x + 1)(0)` does not terminate.
- `fixedPoint(x => if (x % 10 == 0) x else x + 1)(35)` returns `40`.
- `fixedPoint(x => x / 2 + 5)(20)` returns `10`.
## Question 5
### Question 5.1
```scala
def sum(a: Int, b: Int)(f: Int => Int): Int =
@tailrec
def loop(i: Int, acc: Int): Int =
if i > b then acc
else loop(i + 1, acc + f(i))
loop(a, 0)
```
### Question 5.2
```scala
def quadratic(c: Int): Int => Int =
(x: Int) => (x - c) * (x - c)
```
### Question 5.3
```scala
def quad3Integrate(a: Int, b: Int): Int =
sum(a, b - 1)(quadratic(3))
```
# Exercise Session 3, Solutions
## Question 1
```scala
def eq[T](a: T, b: T, leq: (T, T) => Boolean) = leq(a, b) && leq(b, a)
def le[T](a: T, b: T, leq: (T, T) => Boolean) = leq(a, b) && !leq(b, a)
```
## Question 2
Using pattern matching:
```scala
trait Tree[T]:
def size: Int = this match
case EmptyTree(_) => 0
case Node(left, _, right, _) => left.size + 1 + right.size
case class EmptyTree[T](leq: (T, T) => Boolean) extends Tree[T]
case class Node[T](left: Tree[T], elem: T, right: Tree[T], leq: (T, T) => Boolean) extends Tree[T]
```
Defining a method per subclass:
```scala
trait Tree[T]:
def size: Int
case class EmptyTree[T](leq: (T, T) => Boolean) extends Tree[T]:
def size: Int = 0
case class Node[T](left: Tree[T], elem: T, right: Tree[T], leq: (T, T) => Boolean) extends Tree[T]:
def size: Int = left.size + 1 + right.size
```
## Question 3
```scala
def add(newElem: T): Tree[T] = this match
case EmptyTree(leq) =>
Node(EmptyTree(leq), newElem, EmptyTree(leq), leq)
case Node(left, elem, right, leq) =>
if leq(newElem, elem) then
if leq(elem, newElem) then this
else Node(left.add(newElem), elem, right, leq)
else Node(left, elem, right.add(newElem), leq)
```
## Question 4
```scala
def toList: List[T] =
def toListAcc(tree: Tree[T], acc: List[T]): List[T] = tree match
case EmptyTree(_) => acc
case Node(left, elem, right, _) =>
toListAcc(left, elem :: toListAcc(right, acc))
toListAcc(this, Nil)
```
Without using an accumulator:
```scala
def toListNoAcc: List[T] = this match
case EmptyTree(_) => Nil
case Node(left, elem, right, _) =>
(left.toList :+ elem) ++ right.toList
// shortand for left.toList.appended(elem).concat(right.toList)
```
## Question 5
```scala
def sortedList[T](leq: (T, T) => Boolean, ls: List[T]): List[T] =
def buildTree(elems: List[T], acc: Tree[T]): Tree[T] = elems match
case Nil => acc
case elem :: rest => buildTree(rest, acc.add(elem))
buildTree(ls, EmptyTree(leq)).toList
```
## Question 6
```scala
enum Tree[T]:
def size: Int = /* ... */
def add(newElem: T): Tree[T] = /* ... */
def toList: List[T] = /* ... */
case EmptyTree(leq: (T, T) => Boolean)
case Node(left: Tree[T], elem: T, right: Tree[T], leq: (T, T) => Boolean)
```
\ No newline at end of file
......@@ -14,54 +14,31 @@ stages:
compile:
stage: build
timeout: 15m
image: lampepfl/moocs:2021-09-20
timeout: 10m
image: ${DOCKER_REPO}/compile
tags:
- cs210
except:
- tags
- master
- exercise-1
- exercise-2
- exercise-3
- exercise-4
- exercise-5
- exercise-6
- exercise-7
- exercise-8
- main
script:
- sbt packageSubmission
# Output of this job that needs to be stored to be reused in the grade job below
artifacts:
expire_in: 1 day
expire_in: 24h
paths:
- submission.jar
grade:
stage: grade
timeout: 15m
timeout: 10m
except:
- tags
- master
- exercise-1
- exercise-2
- exercise-3
- exercise-4
- exercise-5
- exercise-6
- exercise-7
- exercise-8
- main
tags:
- cs210
image:
name: lampepfl/moocs:cs210-2021-${CI_COMMIT_BRANCH}
entrypoint: [""]
variables:
JAR_PATH: "${CI_PROJECT_DIR}/submission.jar"
image: ${DOCKER_REPO}/grader-${CI_COMMIT_BRANCH}
allow_failure: true
before_script:
- mkdir -p /shared/submission/
- cp submission.jar /shared/submission/submission.jar
script:
- cd /grader
- /grader/grade
- cat /shared/txtFeedback.txt
- grep -q congratulations /shared/txtFeedback.txt
script: "😎"
# Example lab
The goal of this lab is to familiarize yourself with the infrastructure and tools used in this class. Even though the grade in this lab won't influence your grade for the course, it is important that you work through this lab carefully.
## Part 1: Obtaining the Project Files
First, make sure you've followed the [Tools Setup](tools-setup.md) page.
**At this point, we strongly encourage you to take the time to read at least the first three chapters of the [Git Book](https://git-scm.com/book/en/v2). If you just copy-paste the commands we give you without understanding them, it's likely that you'll make a mistake somewhere and waste time. Git can be a huge productivity enhancer when used correctly, so it's definitely worth the investment!**
We'll starting by cloning the repository containing all our lab (make
sure to replace `GASPAR` with your EPFL username (the one with letters, not the
one with number) in the following command).
```shell
git clone -b example git@gitlab.epfl.ch:lamp/students-repositories-fall-2021/cs210-GASPAR.git cs210-example
```
**If this command fails, make sure you've [logged into
gitlab](https://gitlab.epfl.ch/users/sign_in) and [registered in this table](https://docs.google.com/spreadsheets/d/12KvfD_jN5AcApmWhCz7xZmln48fctQOa984RPWrqRkY/edit#gid=0),
then wait a few minutes.
If it still doesn't work it's likely that you didn't correctly upload your ssh
key to gitlab, look at the last part of the [Tools Setup](tools-setup.md) page again.**
```shell
cd cs210-example
```
Now that we've obtained the project, let's take a look at its structure:
```shell
.
├── build.sbt
├── project
│ ├── ...
└── src
├── main
│ └── scala
│ └── example
│ └── Lists.scala
└── test
└── scala
└── example
└── ListsSuite.scala
```
- All the files ending with `.sbt` or in the `project/` directory are build tool configuration files: you don't need to modify them or look at them for any of the labs
- The project sources are in `src/main/scala/`
- The sources of the unit tests are in `src/test/scala/`. You will need to make all the tests pass to complete the labs, and you should write additional tests to check for cases that our tests do not cover.
## Part 2: Using sbt
Start sbt by running:
```shell
sbt
```
Once it's finished starting (this may take a while), you'll be able to enter sbt
commands. You can compile your project using `compile` and run the tests with
`test` (this automatically compiles your code if needed to). Note that if
compilation fails, no tests will be run. The first time you'll run `test` in an
lab you should see many errors: that's normal, your job is to make the
tests pass! But first, let's look at a failed test in detail:
![](images/sbt-test-error.png)
This tells us several things:
- There's a test named `sum of a few numbers (10pts)` in the class `ListsSuite` in the package `example`
- The test failed (that's why it's in red and starts with `==> X`) with an exception: `NotImplementedError`.
- This exception was thrown from the method `???` in `scala.Predef` in the file
`Predef.scala`, this file is not part of our project (that's why it's in
grey), to find the actual error in our code we have to look at where this
method was called from.
- This method was called from method `max` in `example.Lists` in the file
`Lists.scala` at line 40, this is where the bug is!
- It's also important to see where in our test this was called from, here
it's line 102 of `ListsSuite.scala`.
Time to go fix that bug! The next section will show you how to do that using the IDE.
## Part 3: Using the IDE
### Setup
Let's upgrade the IDE support first, close VSCode if it's open and run:
```shell
code --force --install-extension scalameta.metals
```
### Startup
To start Code, run the following in the project directory (the same directory where you
previously ran `sbt`), it's important to run Code in the correct directory or
it won't be able to import your project:
```shell
code .
```
(In this command the `.` is important, it's how we tell Code to run in the
current directory)
(if you see an error `Expected ';'` it means you're inside sbt, open a new
terminal in the same directory)
The first time the IDE starts, it will take some time to download more
components, eventually it will ask you to import the build, please click "Import
build":
![](images/metals-import.png)
You'll need to wait a bit for the import to finish, if an error appears try
closing and restarting Code in the same way we started it above.
### Usage
It's now time to dig in! Earlier we talked about a failing test, the stack trace
told us that it was failing on line 102 of the file `ListsSuite.scala`, so let's open that file:
![](images/open-test.png)
Here's the source code of the test:
![](images/test-source.png)
The first line gives a name to the test, the second line runs
`sum(List(1, 2, 0))` and tests that it equals 3, but in our case we never got to
this point because an exception was thrown, recall that the second line
of the stack trace was:
```scala
at example.Lists$.sum(Lists.scala:25)
```
This tells us that the crash happened when calling `sum`, we can hover with our mouse over the call to `sum` in the test method to get more information on it:
![](images/hover.png)
**If hovering doesn't show this see the [Troubleshooting](#troubleshooting) section.**
The hover is split into two parts: the first part is:
```scala
def sum(xs: List[Int]): Int
```
This means that `sum` is a method that takes a `List` of `Int` as argument and
returns an `Int`. The second part is the documentation of `sum`. We can jump to
the definition of sum by `Ctrl+click` (`Cmd+click` on Mac) or by `right click ->
Go to Definition`. Once there we see:
![](images/sum-def.png)
Now we know why the test failed: `sum` calls `???`, which is a method defined in
the Scala standard library that simply crashes your program: whenever you see it
in a lab it means that this is something you need to replace by your own
implementation.
Once you've implemented this method, you can run `test` from sbt again to see if
the test passed, if you want to run a single test instead of all tests you can
use `testOnly` instead and specify part of the name of the test:
```scala
testOnly -- "--tests=.*max of a few.*"
```
You now know enough to be able to work with the IDE, here are some additional tips:
- When you press `Enter` to make a new line, the IDE will automatically indent the
line if needed (for example, if the last word on the previous line was
`then`), however it will never unindent code for you (for example, when
writing `else`). You can indent code manually by pressing `Tab` and
unindent it by pressing `Backspace` or `Shift + Tab`.
- When working on an lab, you are free to create as many methods, classes and objects as you want. **But you shouldn't change the name of existing methods, classes and objects, because that may break the automated grading system, this is important!**.
- You can see a list of all warnings and errors reported by the compiler by clicking on ![](images/warnings-errors.png) at the bottom left of Code.
- The IDE can show you on hover the documentation of classes, defs and vals defined in the current project but support for external project is currently missing. To compensate for this, you can consult the documentation online:
- The documentation for the Scala standard library is at [https://www.scala-lang.org/files/archive/api/2.13.3/](https://www.scala-lang.org/files/archive/api/2.13.3/)
- The documentation for the Java standard library is at [https://docs.oracle.com/en/java/javase/15/docs/api/index.html](https://docs.oracle.com/en/java/javase/15/docs/api/index.html)
- You can customize Code as much as you want, including installing additional extensions, but please avoid installing other Scala-related extensions: they may conflict with the one we use for this course.
- While working on your lab, you will regularly want to go back to the sbt console to run the tests. You could simply run the command `test` every time, but you can take advantage of the watch mode instead: if a command is prefixed by `~`, sbt will watch the source directory for changes and re-run the command every time a file is saved. So a possible workflow is:
1. Start the IDE
2. Start sbt in the terminal (protip: you can start a terminal inside Code from the
menu: `Terminal -> New Terminal`)
3. Inside sbt, run `~test`
4. Work in the IDE, and check the output of the sbt console from time to time
## Part 4: Running your code
Writing code and running tests is nice, but sometimes more direct feedback is useful, like when you want to experiment with Scala, or try out some methods that you implemented. You can do this using the Scala REPL (Read/Eval/Print Loop) or with a worksheet.
### The REPL
After having started sbt, you can start the REPL by typing `console`, you will see the following prompt:
```scala
scala>
```
At this point you can write any Scala expression you want, for example:
```scala
scala> val l = List(3,7,2)
val l: List[Int] = List(3, 7, 2)
```
(If you write an expression without wrapping it in a `val` or a `def`, the REPL will give it a name for you, starting with `res`)
```scala
scala> l.isEmpty
val res0: Boolean = false
scala> println(res0)
false
scala> l.tail.head
res1: Int = 7
scala> List().isEmpty
res2: Boolean = true
```
The classes of the lab are available inside the REPL, so you can for instance import all the methods from `object Lists` and start using `max`:
```scala
scala> import example.Lists._
import example.Lists._
scala> max(List(1,3,2))
res1: Int = 3
```
You can enter a multiline expression in the REPL by using `Alt+Enter` instead of `Enter`:
```scala
scala> if 1 == 1 then
| "a"
| else
| "b"
val res0: String = a
```
(on macOS, first go to `Terminal -> Preference -> Profiles -> Keyboard` and then
select `Use Option as Meta key`, then `Option+Enter` will work for multiline
expressions.)
In order to exit the Scala REPL and go back to sbt, type `Ctrl+D`.
### The worksheet mode
A *worksheet* is a file where every line of code written in the IDE is executed and its output displayed as a comment.
#### Creating a worksheet
Any file that ends in `.worksheet.sc` is considered to be a worksheet by the IDE. Once Code is launched in a project, all you have to do is create a new file and save it (`Ctrl+N, Ctrl+S`) using any name as long as it ends in `.worksheet.sc`.
#### Using the worksheet mode
Inside this file, you can type any line of code you would type in the REPL. The
worksheet will be automatically run when the code is saved and auto-save is
enabled by default. Each line of code will be executed one by one and its output
will be shown in green on the right.
## Part 5: Submitting your Solution
[Click here to learn how to submit your lab.](grading-and-submission.md)
# Troubleshooting
## sbt fails to start
If you see any kind of error when sbt starts that prevents you from using it,
try cleaning the project cache by running:
```shell
git clean -Xdf
```
Then restarting `sbt`, if this still doesn't work, try deleting the global sbt
cache:
```shell
rm -r ~/.sbt
```
## IDE features like type-on-hover or go-to-definition do not work
It's likely that the build wasn't imported, we can import it manually:
Click on the "m" logo in the left bar (where the red arrow is in the screenshot below):
![](images/menu-metals.png)
In the sidebar that appears, click on "Import build", then wait a bit:
![](images/import-build.png)
If things still don't work, try restarting Code (launch it in the same way you
started it before, using `code .` from the project directory). If you're still
having issues, try clicking on "Clean compile workspace" from the same
sidebar.
## Warning about Bloop installed version
If you get a warning like this:
![](images/bloop-update.png)
Please click the first button "Turn off old server".
# Grading and submission
## Local tests and grading
Each lab is shipped with two sets of tests:
* The tests defined under `src/test/scala`, these are usually incomplete: we
strongly encourage you to write additional tests to exercise every aspect of
your code. You can run these tests from `sbt` using the following command:
```shell
test
```
* The **grading tests**, that we use to grade your labs, these are
provided as a "black box": you can run them but are not allowed to see their
content, to encourage you to write your own tests. You can run them from
`sbt` using the following command:
```shell
Grading/test
```
Your grade is determined by the number of these tests that pass, see the
next section to see how to actually get a grade.
(remember that you can always put `~` before an sbt command to automatically
re-run it when you save a file)
## Committing and pushing your code
**You need to push your code to gitlab before the deadline for the lab to
receive a grade. If you forget, your grade will be zero.**
If you've read the first few chapters of [Git
book](https://git-scm.com/book/en/v2) as recommended, you must already be
familiar with committing and pushing, but let's go over the basics once again:
At any point while working on an lab, you can see what changes you
haven't committed by writing:
```shell
git status
```
(If you get the error `Not a valid command: git`, it means you're inside sbt,
you can't run git from sbt itself, you need to open another terminal in the same
directory)
This will display the list of files you have modified since the last commit, to
see the exact changes you made, run:
```shell
git diff
```
To save these changes in a commit, run: (replace `"My message"` by a message
describing the changes since the last commit, see [How to Write a Git Commit
Message](https://chris.beams.io/posts/git-commit/) for some tips on writing
good commit messages)
```shell
git commit -am "My message"
```
(It's good practice to commit your code regularly to document your changes)
You can then synchronize your local git repository with the gitlab server by
first running:
```shell
git pull --no-rebase
```
This will merge in your local repository any change we made to the lab
(we only change labs to fix critical bugs found after it's been released,
so most of the time this will not do anything).
Finally, you can push your changes to gitlab:
```shell
git push
```
Note that there are also graphical user interfaces to interact with git, for
example [VSCode has built-in git
support](https://code.visualstudio.com/docs/editor/versioncontrol#_git-support).
Once you've pushed your code, you can see the result online by going to
`gitlab.epfl.ch/lamp/students-repositories-fall-2021/cs210-GASPAR/pipelines` where
`GASPAR` is your username (you can also access this page from the main page of
your repository by clicking on the rocket icon on the left side of the gitlab
interface, then clicking on "Pipelines").
![](images/pipeline-tab.png)
The grading pipeline contains two steps:
* *compile*: your code does not compile for grading if the job fail.
* *grade*: the job results in a warning if you do not get the maximum grade
(10.00/10.00)
If a job is marked "pending", it means there are other students running jobs at
the same time and you'll have to wait a bit for your job to run.
You can click on the `grade` job to see its output:
![](images/pipeline-details.png)
![](images/pipeline-logs.png)
Your grade is given on the line that starts with `Your overall score for this
lab is`
**If you push to gitlab multiple times, your final grade will be based on the
last commit you pushed before the deadline.**
labs/images/bloop-update.png

18.1 KiB

labs/images/clone-url.png

41.8 KiB

labs/images/gitlab-public-ssh-key.png

111 KiB

labs/images/gitlab-settings.png

24.8 KiB

labs/images/hover.png

163 KiB

labs/images/import-build.png

35.3 KiB

labs/images/menu-metals.png

54.6 KiB

labs/images/metals-import.png

30.4 KiB

labs/images/open-test.png

17.6 KiB