Modulo three the right side is always minus one, a nonsquare. At two, gives the square 2-adic integer . At twenty-three the same value is a nonzero square modulo the prime and lifts by Hensel's lemma. At every other prime at least five, the model has good reduction of an elliptic curve and the Hasse bound gives more than its single point at infinity, hence an affine smooth point. Lifting that point gives p-adic integer coordinates.
Model-view-controller divides an interactive application into a model containing application state and domain rules, a view rendering that state, and a controller interpreting user actions and requesting model operations. In the converter, the numeric amounts and exchange relation belong to the model, the text fields and labels form the view, and the edit handler parses input and chooses which quantity to preserve. A playlist model similarly owns song order independently of the controls used to change it.
A user acts through the view, the controller interprets that input, the model validates and commits a change, and the view then renders the resulting state. The exact packaging varies: a widget can combine view and controller responsibilities while still separating domain logic. Keeping the model independent of particular controls supports separation of concerns, encapsulation, reuse of the same model in several views, and unit testing of domain behavior without a graphical interface.
The Observer pattern often supplies the model-to-view notification path: views subscribe to model changes, so the model need not directly know every concrete view. It can also carry view input events to a controller, as in Scala Swing. Model-view-controller is an architectural separation of responsibilities; the Observer pattern is one mechanism for their communication. They are related without being identical, and small applications can implement the separation with direct calls where event subscriptions add no benefit.
Choose a deterministic editing policy: editing pounds or the exchange rate preserves the pounds amount and recalculates euros; editing euros preserves the rate and recalculates pounds. A valid rate must be finite and positive; amounts may be any finite signed number. Keep an unrounded numeric model, so repeatedly refreshing a two-decimal display does not feed rounded text back into the computation. Place the following members inside the supplied MainFrame, after its fields are created:
private var poundsValue = 10.0
private var eurosValue = 11.5
private var rateValue = 1.15
private var refreshing = false

private def finite(x: Double): Boolean =
  !java.lang.Double.isNaN(x) && !java.lang.Double.isInfinite(x)

private def number(s: String): Option[Double] =
  scala.util.Try(s.trim.toDouble).toOption.filter(finite)

private def money(x: Double): String =
  java.lang.String.format(java.util.Locale.ROOT, "%.2f",
                          java.lang.Double.valueOf(x))

private def refresh(): Unit = {
  refreshing = true
  try {
    pounds.text = money(poundsValue)
    euros.text = money(eurosValue)
    rate.text = money(rateValue)
  } finally {
    refreshing = false
  }
}

private def commit(p: Double, e: Double, r: Double): Unit = {
  if (finite(p) && finite(e) && finite(r) && r > 0.0) {
    poundsValue = p
    eurosValue = e
    rateValue = r
    refresh()
  }
}

listenTo(pounds, euros, rate)
reactions += {
  case EditDone(source) if !refreshing =>
    number(source.text).foreach { value =>
      if (source eq pounds)
        commit(value, value * rateValue, rateValue)
      else if (source eq euros)
        commit(value / rateValue, value, rateValue)
      else if ((source eq rate) && value > 0.0)
        commit(poundsValue, poundsValue * value, value)
    }
}
The mathematical model invariant is with a positive rate. In floating-point arithmetic, each update establishes the corresponding rounded multiplication or division; a division followed by multiplication need not recover bitwise identical values. Pounds and rate edits calculate a matching euro amount, while euro edits calculate its matching pound amount. An invalid parse, a nonpositive rate, or a nonfinite calculated result leaves the last valid numeric model unchanged. An invalid text entry may remain visible until corrected or a subsequent valid refresh; a production interface could add a validation message.
Every accepted edit refreshes the fields from that model. Locale.ROOT makes the decimal separator match the toDouble parser, independently of the machine's locale. The guard prevents a synchronous reentrant event handler from interpreting a refresh as another user commit. The displayed values are rounded to two decimal places, including the rate, while the stored values retain full Double precision. Very small positive rates can therefore display as 0.00; using more rate digits is a reasonable presentation refinement. Pounds, euros and rate edits all propagate by the stated policy, with no parsing exception or division by zero.
EditDone handles completion of an edit, such as an action or focus-change notification, using the event type supplied in the paper. It is not a promise of recalculation after every keystroke. A character-by-character interface would subscribe to the corresponding text-change event instead. The publisher/reactor interaction follows the supplied contract and official Scala Swing documentation; no exact course library build or native graphical execution is presumed.[ref]
A Scala Swing Publisher is the subject-side event source. Calling publish(e) notifies its subscribed reactors. A Reactor is the observer-side participant: listenTo(p1,p2) registers it with the specified sources, deafTo ends those subscriptions, and reactions contains the event-handling cases.
listenTo(pounds, euros, rate)
reactions += {
  case EditDone(source) => handleCommittedEdit(source)
}
Here the containing frame supplies the reactor behavior, and each text field supplies publication. Defining reactions without listenTo is insufficient to establish the subscription. The pattern-matching cases can handle only events of interest while other events are ignored. This is the Observer pattern expressed through event publication rather than a separate hand-written update method for every subject.[ref]
In the Observer pattern, an observable subject maintains subscriptions and sends notifications through a common observer interface when a relevant change occurs. Observers can then react to the event or query the subject's coherent new state. Registration and removal allow multiple dependants to change independently of the subject's application logic.
It is useful when one software object has several changing dependants, for example a document model with several views or a text field with an event handler. It avoids hard-coding every concrete dependant into the subject, reducing direct coupling and duplicated synchronization logic. Clients need not poll repeatedly to detect a change. This separation does not automatically prevent notification cycles, stale subscriptions, or inconsistent intermediate states: notification should occur after a coherent update, and observers should unregister when no longer needed. A reentrant event handler can otherwise commit recursively while refreshing a display.
Declare +U, keep its stored linked list immutable, and generalize operations that need to accept output values by a fresh lower type bound:
class PartialFn[T, +U](val data: List[(T, U)]) {
  def get(x: T): Option[U] =
    data.find { case (key, _) => key == x }.map(_._2)

  def remove(x: T): PartialFn[T, U] =
    new PartialFn[T, U](data.filterNot { case (key, _) => key == x })

  def add[V >: U](x: T, y: V): PartialFn[T, V] =
    new PartialFn[T, V]((x, y) ::
      data.filterNot { case (key, _) => key == x })

  def compose[V >: U, W](that: PartialFn[V, W]): PartialFn[T, W] = {
    val pairs: List[(T, W)] = data.flatMap {
      case (x, y) => that.get(y).map(z => (x, z)).toList
    }
    new PartialFn[T, W](pairs)
  }
}
get, remove, and the immutable val data expose U in covariant result positions: Scala's immutable List, Tuple2 and Option preserve that position. The old add(x:T,y:U) consumed U directly, violating the variance-position rule. The new add accepts a value of a chosen supertype V and returns a new mapping with that widened output type; it never inserts the wider value into the old narrower mapping.
The original compose also mentions U as the first, invariant parameter of PartialFn[U,V]. Changing only add is therefore insufficient. Its new first type parameter V >: U is independent of the class's covariant parameter except for the allowed lower bound. Any stored y:U is acceptable to that.get as a V, while the result has output type W. This lower type bound solution avoids unchecked variance annotations or casts. The official variance rules illustrate the same lower-bound widening technique for an immutable collection's consuming method; the later 2.13 text corroborates the rule, without identifying an installed 2018 compiler version.[ref]
A covariant type parameter preserves subtyping: if , then PartialFn[T,A] <: PartialFn[T,B] when its second parameter is covariant. In Scala the class annotation is +U. A mapping that produces a narrower output can be used where a broader output is expected. Covariance describes a type relationship; it does not convert stored values or make mutation through a widened reference safe.[ref]
The second partial function accepts this one's outputs. Put this method inside the invariant class in part (b):
def compose[V](that: PartialFn[U, V]): PartialFn[T, V] = {
  val pairs: List[(T, V)] = data.flatMap {
    case (x, y) => that.get(y).map(z => (x, z)).toList
  }
  new PartialFn[T, V](pairs)
}
The represented mapping is , since the paper explicitly applies that second despite the method name. A pair is emitted exactly when this mapping supplies a y and that.get(y) supplies a z. Hence its domain of a partial function is and its value there is . This is strict composition of partial functions: either missing stage makes the composite undefined. Repeated equal input pairs still produce the same output, preserving the representation invariant. With and pairs, direct association-list lookup gives worst-case time complexity, not a hidden constant-cost dictionary lookup.
Use pattern matching and an optional value to distinguish absence from a present result:
class PartialFn[T, U](val data: List[(T, U)]) {
  def get(x: T): Option[U] =
    data.find { case (key, _) => key == x }.map(_._2)

  def remove(x: T): PartialFn[T, U] =
    new PartialFn[T, U](data.filterNot { case (key, _) => key == x })

  def add(x: T, y: U): PartialFn[T, U] =
    new PartialFn[T, U]((x, y) ::
      data.filterNot { case (key, _) => key == x })
}
The representation precondition is that equal keys always have equal associated values, with a stable equality relation on keys. This permits harmless repeated identical pairs; it excludes conflicting outputs for one input. get therefore returns Some(y) exactly when the represented partial function is defined at x. Removing filters out every occurrence of the key and leaves all other pairs unchanged. Adding first removes every old occurrence and prepends exactly the new pair, proving the partial function update postcondition even if the input contains duplicate identical pairs. The immutable linked list representation leaves the original mapping unchanged. Each operation has worst-case time complexity for pairs under constant-cost key equality.
Programming language polymorphism means that one interface or program definition can be used with values of multiple types. In object-oriented programming, subtype polymorphism allows references with a common static type to denote instances of different concrete subclasses or implementers of a trait. An object method call uses dynamic dispatch to select the overriding implementation belonging to the receiver's runtime type. For example, different implementations of a playlist interface can respond to the same insert call without the client testing their concrete classes.
Parametric polymorphism uses type parameters, as in Sequence[A], so the same definition works uniformly for songs, integers, or other elements. Ad hoc polymorphism includes method overloading, where different parameter signatures share a name and the static types determine overload selection. These mechanisms are distinct: selecting an overloaded signature is not the same step as dispatching an override of that selected signature. Class inheritance can supply implementations, but the reusable interface and legal subtyping relationship determine what a polymorphic client may do.
The Command pattern separates a request into a common command interface, concrete commands carrying arguments and execution behavior, a receiver doing the application work, an invoker requesting execution or retaining history, and a client assembling these software objects. A menu item, toolbar button or keyboard shortcut can invoke the same command without duplicating the playlist manipulation.
SongSuite is the receiver. The application/controller invokes its operations, and the returned Change software objects hold the concrete inverse/forward behavior. A command wrapper can expose an initial execute that calls the appropriate SongSuite operation and then delegates later undo/redo to its returned record. History is the history-managing part of the invoker. Separating these roles avoids making a graphical control know how the playlist representation is edited; requests can be retained and reversed through a common object interface.
Use an inverse edit record with a common undo/redo interface. Positions are zero-based. For move(i,j), j is the song's final index after the move, so it is also the insertion index in the shortened sequence. For an original length , require ; insertion permits and deletion requires . As allowed, the caller guarantees validity.
trait Change {
  def undo(): Unit
  def redo(): Unit
}

class SongSuite(initial: Sequence[Song]) {
  private var songs = initial
  def length: Int = songs.length
  def elementAt(i: Int): Song = songs.elementAt(i)

  private def rawInsert(i: Int, x: Song): Unit = {
    songs = songs.insert(i, x)
  }
  private def rawDelete(i: Int): Unit = {
    songs = songs.delete(i)
  }
  private def rawMove(i: Int, j: Int): Unit = {
    val x = songs.elementAt(i)
    songs = songs.delete(i)
    songs = songs.insert(j, x)
  }
  private def perform(forward: () => Unit,
                      backward: () => Unit): Change = {
    forward()
    new Change {
      def undo(): Unit = backward()
      def redo(): Unit = forward()
    }
  }
  def insert(i: Int, x: Song): Change =
    perform(() => rawInsert(i, x), () => rawDelete(i))

  def delete(i: Int): Change = {
    val x = songs.elementAt(i)
    perform(() => rawDelete(i), () => rawInsert(i, x))
  }
  def move(i: Int, j: Int): Change =
    perform(() => rawMove(i, j), () => rawMove(j, i))
}
Song denotes the application's song type, whose internal fields are irrelevant to these operations. Sequence denotes the supplied interface; each returned sequence is assigned back, so the code does not discard the result of a functional implementation. SongSuite owns its current sequence; independent mutations through outside aliases are excluded. Atomic successful edits and an ordinary sequential history are assumed.
For inverse command correctness, inserting at is reversed by deleting at ; deleting at is reversed by reinserting the saved song there. After moving from to , removing the moved song at recovers the original sequence with that one entry missing, and reinserting it at restores the original. This also covers . Store the actual deleted song reference, rather than identifying it by title, since duplicate songs may occur.
The edits have already executed when returned. A history manager can enforce the chronological protocol with two stacks:
class History {
  private var done: List[Change] = Nil
  private var undone: List[Change] = Nil
  def record(c: Change): Unit = {
    done = c :: done
    undone = Nil
  }
  def undo(): Unit = {
    require(done.nonEmpty)
    val c = done.head
    c.undo()
    done = done.tail
    undone = c :: undone
  }
  def redo(): Unit = {
    require(undone.nonEmpty)
    val c = undone.head
    c.redo()
    undone = undone.tail
    done = c :: done
  }
}
For example, history.record(suite.move(i,j)) records an applied move. The history invariant says that the current playlist results from the applied prefix, the top of done is its last edit, and the top of undone is the first next edit available for redo. Each transfer preserves this invariant. A fresh edit clears the redo branch. Calling an arbitrary old inverse after unrelated edits is outside this protocol and need not be correct.
Return the new root of the affected subtree, assigning that result back to the parent's child reference:
def addToTree(word: String, t: Tree): Tree = {
  require(word != null)
  if (t == null) new Tree(word, 1)
  else {
    val c = word.compareTo(t.word)
    if (c < 0) t.left = addToTree(word, t.left)
    else if (c > 0) t.right = addToTree(word, t.right)
    else {
      require(t.count < Int.MaxValue)
      t.count += 1
    }
    t
  }
}
// Updating the whole structure uses: root = addToTree(word, root)
Assume the input binary search tree satisfies part (b)'s representation invariant and, if the key already occurs, its count can be incremented. Structural induction proves the postcondition. For an empty subtree, the fresh entry represents one occurrence. Otherwise the word comparison identifies the only possible child subtree containing the word. The recursive call adds exactly one occurrence there, preserving the inherited strict bounds; in the equal case only the count changes. The number of entries in the current subtree strictly decreases in each recursive call, proving algorithm termination. The returned binary search tree represents the old multiset plus one occurrence of word. With height , at most comparisons are made; without balancing this can be linear in the number of words. Actual comparison work also depends on the compared string data type lengths.
The representation invariant says that root is either null or the root of a finite, acyclic binary search tree, with no software object shared between different child subtrees. Every reachable entry has a non-null word and a strictly positive frequency. For each entry , every word in its entire left subtree is strictly less than t.word, and every word in its entire right subtree is strictly greater. This is an inherited ordering condition on all descendants, rather than merely a comparison with immediate children. It implies that each distinct word has exactly one entry. The empty initial state satisfies it.
The abstraction function is the finite multiset assigning each stored word its positive count and assigning all other words zero. Frequencies and their increments must fit in Int; the implementation below explicitly rejects an increment at its representational limit instead of silently violating positivity through integer overflow.
Each binary tree entry stores its word, positive frequency, and two child references:
class Tree(val word: String, var count: Int,
           var left: Tree = null, var right: Tree = null)
A null reference denotes an empty subtree. A word is a non-null string data type value; its order below is the fixed lexicographic order used by String.compareTo.

Pinned article: Introduction to the OurBigBook Project

Welcome to the OurBigBook Project! Our goal is to create the perfect publishing platform for STEM subjects, and get university-level students to write the best free STEM tutorials ever.
Everyone is welcome to create an account and play with the site: ourbigbook.com/go/register. We belive that students themselves can write amazing tutorials, but teachers are welcome too. You can write about anything you want, it doesn't have to be STEM or even educational. Silly test content is very welcome and you won't be penalized in any way. Just keep it legal!
We have two killer features:
  1. topics: topics group articles by different users with the same title, e.g. here is the topic for the "Fundamental Theorem of Calculus" ourbigbook.com/go/topic/fundamental-theorem-of-calculus
    Articles of different users are sorted by upvote within each article page. This feature is a bit like:
    • a Wikipedia where each user can have their own version of each article
    • a Q&A website like Stack Overflow, where multiple people can give their views on a given topic, and the best ones are sorted by upvote. Except you don't need to wait for someone to ask first, and any topic goes, no matter how narrow or broad
    This feature makes it possible for readers to find better explanations of any topic created by other writers. And it allows writers to create an explanation in a place that readers might actually find it.
    Figure 1.
    Screenshot of the "Derivative" topic page
    . View it live at: ourbigbook.com/go/topic/derivative
  2. local editing: you can store all your personal knowledge base content locally in a plaintext markup format that can be edited locally and published either:
    This way you can be sure that even if OurBigBook.com were to go down one day (which we have no plans to do as it is quite cheap to host!), your content will still be perfectly readable as a static site.
    Figure 5. . You can also edit articles on the Web editor without installing anything locally.
    Video 3.
    Edit locally and publish demo
    . Source. This shows editing OurBigBook Markup and publishing it using the Visual Studio Code extension.
  3. https://raw.githubusercontent.com/ourbigbook/ourbigbook-media/master/feature/x/hilbert-space-arrow.png
  4. Infinitely deep tables of contents:
    Figure 6.
    Dynamic article tree with infinitely deep table of contents
    .
    Descendant pages can also show up as toplevel e.g.: ourbigbook.com/cirosantilli/chordate-subclade
All our software is open source and hosted at: github.com/ourbigbook/ourbigbook
Further documentation can be found at: docs.ourbigbook.com
Feel free to reach our to us for any help or suggestions: docs.ourbigbook.com/#contact