HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Conjugation tables for French

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
conjugationtablesforfrench

Problem

I'm in the process of structuring a model for conjugation tables for French. There are noun inflections, adverb inflections, and 19 verb conjugations. I'm trying to model the data so that every piece of data is accessible in the same manner as one would traverse the following XML tree (taken from my XML dictionary file):










































Here is the way that I've found to model the data. This is simply a storage mechanism. Basically it's necessary to have the entire dictionary in memory (maybe excluding standard verb conjugations but that just makes things more complicated - I can optimize on that later). This will allow instant lookup of a word in the application. The Words will be stored in a SortedDictionary as a data member of another class. There will also be a separate implementation of a spell checker.

Grammar-specific data should not be a part of this schema. Simply put, special exceptions such as the word bel (inflection of beau coming before a word that starts with a vowel) will be handled separately in the grammar interface of the application. This design is meant to store common attributes among all words in a dictionary, such as noun/adjective inflections, verb conjugations, and other small pieces of data like definition(s), grammatical forms the word has, etc.

Here's what I have, and will improve upon based on other answers noted here (at least to the best of my ability):

`class Word
{
// the infinitive Word in the Dictionary
public string word { get; set; }
// Whether or not the Word is aspirate - adjective forms and phonetics change.
public bool aspirate { get; set; }
/*
* The list of grammatic

Solution

Let's see what we've got here: a NounTable, inherited from a ConjugationTable. As I mentioned in the comments, this huge comment is unnecessary.

You say you're worried about memory? string is a reference type, with the overhead it incurs. Consider this (I renamed the identifiers just to mess you up see what it would look like):

public enum Genre
{
    Indéterminé,
    Masculin,
    Feminin
}

public enum Nombre
{
    Singulier,
    Pluriel
}

public struct Nom
{
    public Genre Genre { get; set; }
    public Nombre Nombre { get; set; }
}


Notice I haven't derived the NounTable class from a base type. You Ain't Gonna Need It. Besides, you don't derive a bunch of classes because you want to share functionality - remember, a base class puts your type in a is-a inheritance scheme, and if all you want is shared functionality you should favor composition over inheritance. Anyway I made it a struct that stores what can be seen as two int values. It's just fortunate that this happens to mootinate the long comment ;)

What's your spec? Are you implementing the French grammar? I was going to make a long rewrite of the thing - given how simple it is to conjugate 90% of French verbs (1st group), I was going to suggest coding the grammar for it - this could spare you from storing 90% of your verbs dictionary.

And then I deleted it all, it wasn't going to be a helpful answer.

Your code is making beginner mistakes that ought to be addressed first.

If you're copying code, you're doing it wrong.

When you create a base class, its inheritors actually inherit the base members, so any class derived from Indicative does not need to re-implement the base members... but because you have declared them abstract, now you have to. They could have been virtual and that would have left you with classes that look like this:

class IndicativePresent : Indicative
{
}


Not very useful is it? I think all these classes are trying to do one thing: store a string value for the result of the conjugation of a verb at a specified tense, for each person. If that's the case, you could have a IReadOnlyDictionary as a sole member.

I'll end this with a bit of abstract food for thought - if what you're trying to do is really modelize French and implement its grammar, you're probably better off defining every concept as an abstraction:

public enum Person
{
    First,
    Second,
    Third
}

public enum Gender
{
    Undetermined,
    Masculine,
    Feminine
}

public enum Number
{
    Singular,
    Plural
}

public interface IPronoun
{
    Person Person { get; }
    Gender Gender { get; }
    Number Number { get; }
    string Text { get; }
}

public enum VerbGroup
{
    First,
    Second,
    Third
}

public enum VerbAuxiliary
{
    ToHave,
    ToBe
}

public enum VerbTense
{
    Present,
    Past,
    Future
}

public enum VerbMood
{
    Infinitive,
    Indicative,
    Imperative,
    Conditional,
    Subjonctive,
    Participle,
    Gerundive
}

public enum VerbTransitivity
{
    Intransitive,
    Direct,
    Indirect,
    //...
}

public interface IVerb
{
    string InfinitivePresent { get; }
    VerbGroup { get; }
    bool IsPronomial { get; }

    // having these below members here implies the transitive and intransitive forms of
    //  { descendre, monter, passer, redescendre, remonter, rentrer, 
    //   repasser, ressortir, ressusciter, retourner, sortir, tomber}
    // must be implemented as distinct instances.
    VerbAuxiliary { get; }
    VerbTransitivity Transitivity { get; }
}

public interface IConjugable
{
    // an overload taking an IVerb with VerbAuxiliary and VerbTransitivity parameters
    // would allow us to remove these two members from the IVerb implementations,
    // allowing verbs like "passer" and "sortir" (^^^) to only be implemented once.
    string Conjugate(IPronoun subject);
}


If all you're trying to do is to read data from a source, your data-structures should simply reflect it. It feels to me that the inheritance hierarchy obscures the intent of the code, which makes it hard to review without a bit more context.

Code Snippets

public enum Genre
{
    Indéterminé,
    Masculin,
    Feminin
}

public enum Nombre
{
    Singulier,
    Pluriel
}

public struct Nom
{
    public Genre Genre { get; set; }
    public Nombre Nombre { get; set; }
}
class IndicativePresent : Indicative
{
}
public enum Person
{
    First,
    Second,
    Third
}

public enum Gender
{
    Undetermined,
    Masculine,
    Feminine
}

public enum Number
{
    Singular,
    Plural
}

public interface IPronoun
{
    Person Person { get; }
    Gender Gender { get; }
    Number Number { get; }
    string Text { get; }
}

public enum VerbGroup
{
    First,
    Second,
    Third
}

public enum VerbAuxiliary
{
    ToHave,
    ToBe
}

public enum VerbTense
{
    Present,
    Past,
    Future
}

public enum VerbMood
{
    Infinitive,
    Indicative,
    Imperative,
    Conditional,
    Subjonctive,
    Participle,
    Gerundive
}

public enum VerbTransitivity
{
    Intransitive,
    Direct,
    Indirect,
    //...
}

public interface IVerb
{
    string InfinitivePresent { get; }
    VerbGroup { get; }
    bool IsPronomial { get; }

    // having these below members here implies the transitive and intransitive forms of
    //  { descendre, monter, passer, redescendre, remonter, rentrer, 
    //   repasser, ressortir, ressusciter, retourner, sortir, tomber}
    // must be implemented as distinct instances.
    VerbAuxiliary { get; }
    VerbTransitivity Transitivity { get; }
}

public interface IConjugable
{
    // an overload taking an IVerb with VerbAuxiliary and VerbTransitivity parameters
    // would allow us to remove these two members from the IVerb implementations,
    // allowing verbs like "passer" and "sortir" (^^^) to only be implemented once.
    string Conjugate(IPronoun subject);
}

Context

StackExchange Code Review Q#40868, answer score: 6

Revisions (0)

No revisions yet.