Tracks
/
Factor
Factor
/
Exercises
/
Dragons' Descendants
Dragons' Descendants

Dragons' Descendants

Learning Exercise

Introduction

Tuples can extend other tuples. TUPLE: child < parent slots ; declares a class whose instances are also instances of parent — they get the parent's slots in addition to their own, and the parent's accessors work on them too, just as if they'd been defined on the child.

USING: accessors ;

TUPLE: animal name age ;
TUPLE: dog < animal breed ;

"Rex" 4 "labrador" dog boa .
! => T{ dog { name "Rex" } { age 4 } { breed "labrador" } }

"Rex" 4 "labrador" dog boa name>> .   ! => "Rex"   (inherited accessor)

boa slot order

The boa constructor takes slots in declaration order, parents first. For dog above:

dog boa ( name age breed -- dog )

A grandchild puppy < dog adding weeks would be:

puppy boa ( name age breed weeks -- puppy )

Predicate hierarchy

Every TUPLE: declaration generates a predicate (name?). With inheritance the predicates nest — every descendant satisfies its ancestors' predicates:

"Rex" 4 "labrador" dog boa
dup dog? .        ! => t
dup animal? .     ! => t

The reverse isn't true: an animal that isn't a dog fails dog?.

Forward note

Generic methods (M:, taught in generics) dispatch up the hierarchy too — a method on animal fires for every descendant unless a more-specific override takes priority. You'll see that in boatswains-bilge immediately after this exercise.

Instructions

A naturalist is cataloguing the dragons that live around the caldera. They share traits with one another — every dragon has a name, colour, and age — but specialise in distinctive ways. You'll build a small inheritance tree of dragon classes and a single word that ages any descendant.

1. The dragon family

Define the whole inheritance tree of tuple classes up front (their constructors come in the tasks that follow):

  • dragon with slots name, color, age.
  • fire-dragon, a subclass of dragon, adding a flame-temp slot.
  • ice-dragon, another subclass of dragon, adding a chill-temp slot.
  • volcano-dragon, a subclass of fire-dragon, adding a lava-volume slot.

Then give dragon a <dragon> constructor.

"Falkor" "white" 100 <dragon> name>> .   ! => "Falkor"

2. The fire breathers

Give fire-dragon a <fire-dragon> constructor.

"Smaug" "red" 500 1200 <fire-dragon> flame-temp>> .   ! => 1200
"Smaug" "red" 500 1200 <fire-dragon> dragon? .        ! => t

3. The ice breathers

Give ice-dragon a <ice-dragon> constructor.

"Frosty" "blue" 200 -40 <ice-dragon> chill-temp>> .   ! => -40
"Frosty" "blue" 200 -40 <ice-dragon> fire-dragon? .   ! => f   (siblings)

4. The volcano dwellers

Give volcano-dragon a <volcano-dragon> constructor.

"Vesuvius" "red" 1000 1500 99 <volcano-dragon> dragon? .       ! => t
"Vesuvius" "red" 1000 1500 99 <volcano-dragon> fire-dragon? .  ! => t

5. Aging any dragon

Define age-dragon to increment the age slot of any dragon (or descendant) by one. Returns nothing.

"Falkor" "white" 100 <dragon> dup age-dragon age>> .   ! => 101

The same word should work on every descendant — that's the whole point of the shared accessor.

Edit via GitHub The link opens in a new window or tab
Factor Exercism

Ready to start Dragons' Descendants?

Sign up to Exercism to learn and master Factor with 47 concepts163 exercises, and real human mentoring, all for free.