Násobení matic a automatické přetypování

Inkvizitor

Re:Násobení matic a automatické přetypování
« Odpověď #30 kdy: 17. 09. 2015, 20:50:40 »
Naprasený příklad ve Scale:

Kód: [Vybrat]
package matrix {
class Matrix(array: Array[Array[Double]]) {
  private val elements = array
  def toArray(): Array[Array[Double]] = {
    this.elements
  }
  def isSquareMatrix() : Boolean = {
    val numRows = this.elements.length
    for (subArray <- this.elements) {
      if (subArray.length != numRows) return false
    }
    return true
  }
}

class SquareMatrix(array : Array[Array[Double]]) extends Matrix(array) {
  def trace() : Float = {
    return 0; // dummy
  }
}
}

import java.lang.RuntimeException
import matrix._
object MatrixApp extends App {
  implicit def toSquareMatrix(m: Matrix) : SquareMatrix = {
    if (!m.isSquareMatrix()) throw new RuntimeException("Not a square matrix!")
    return new SquareMatrix(m.toArray())
  }
 
  val m = new Matrix(Array(Array(1.0, 2.0),Array(1.0, 2.0, 3.0)));
  println(m.trace())
}

Implicitní ve Scale umožňuje volat metody třídy SquareMatrix ad hoc, což je lepší než drátem do oka, ale samozřejmě to znamená, že se bude znovu a znovu kontrolovat, zda na to má nárok.

Problém ale je, co s tím dál. Pro matematické problémy typu počítání s maticemi je OOP extrémně nevhodné. Matice není nic jiného než dvourozměrné pole čísel a jako taková nepotřebuje žádné metody, stačí sada funkcí, které pracují nad dvourozměrnými poli, jestli je matice čtvercová nebo ne, je jednoduchý test a stačí ho udělat jenom jednou a pak už výpočet prostě ví, že je ve větvi, kde se dá pracovat se čtvercovou maticí anebo není.

Suma sumárum, pokud to měl být příklad, byl dost nevhodný a pokud fakt autor potřebuje řešit matice, moje rada je se na celé OOP vykašlat. Nehledě na to, že knihoven pro práci s maticemi budou mraky.


zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #31 kdy: 17. 09. 2015, 21:01:56 »
Naprasený příklad ve Scale:

Kód: [Vybrat]
package matrix {
class Matrix(array: Array[Array[Double]]) {
  private val elements = array
  def toArray(): Array[Array[Double]] = {
    this.elements
  }
  def isSquareMatrix() : Boolean = {
    val numRows = this.elements.length
    for (subArray <- this.elements) {
      if (subArray.length != numRows) return false
    }
    return true
  }
}

class SquareMatrix(array : Array[Array[Double]]) extends Matrix(array) {
  def trace() : Float = {
    return 0; // dummy
  }
}
}

import java.lang.RuntimeException
import matrix._
object MatrixApp extends App {
  implicit def toSquareMatrix(m: Matrix) : SquareMatrix = {
    if (!m.isSquareMatrix()) throw new RuntimeException("Not a square matrix!")
    return new SquareMatrix(m.toArray())
  }
 
  val m = new Matrix(Array(Array(1.0, 2.0),Array(1.0, 2.0, 3.0)));
  println(m.trace())
}

Implicitní ve Scale umožňuje volat metody třídy SquareMatrix ad hoc, což je lepší než drátem do oka, ale samozřejmě to znamená, že se bude znovu a znovu kontrolovat, zda na to má nárok.

Problém ale je, co s tím dál. Pro matematické problémy typu počítání s maticemi je OOP extrémně nevhodné. Matice není nic jiného než dvourozměrné pole čísel a jako taková nepotřebuje žádné metody, stačí sada funkcí, které pracují nad dvourozměrnými poli, jestli je matice čtvercová nebo ne, je jednoduchý test a stačí ho udělat jenom jednou a pak už výpočet prostě ví, že je ve větvi, kde se dá pracovat se čtvercovou maticí anebo není.

Suma sumárum, pokud to měl být příklad, byl dost nevhodný a pokud fakt autor potřebuje řešit matice, moje rada je se na celé OOP vykašlat. Nehledě na to, že knihoven pro práci s maticemi budou mraky.
Přesně k tomu to vede, vykašlat se na OOP. Matice jsou ještě jednoduché, větší sranda je s tenzory a operacemi nad nimi. Jde to napsat objektově, ale spíš přes protokoly než dědičnost. Příklad je ostatně ve vedlejším vlákně o čtvercích a rovnoběžnících, kde je řešení přes protokoly to nejjednodušší (a nejefektivnější).

Alt

Re:Násobení matic a automatické přetypování
« Odpověď #32 kdy: 17. 09. 2015, 21:05:17 »
V dynamickém jazyce to půjde vždy, to je jasné. Tady se řeší staticky typovaný jazyk.

Tak som oprasil c++

Kód: [Vybrat]
#include <iostream>

class Matica {
    protected:
        int riadky;
        int stlpce;
    public:
        Matica(int, int);
        Matica* sucin(Matica *);
        virtual void typ() { std::cout << "Matica " << this->riadky << ", " << this->stlpce << "\n"; }
};

class StvMatica: public Matica {
    public:
        StvMatica (int r, int s) : Matica (r, s) {}
        virtual void typ() { std::cout << "Stvorcova Matica " << this->riadky << ", " << this->stlpce << "\n"; }
};

Matica::Matica(int r, int s)
{
    this->riadky=r;
    this->stlpce=s;
}

Matica* Matica::sucin(Matica *matica)
{
    Matica *sucin;
    if (this->stlpce == matica->riadky)
        sucin = new StvMatica(matica->riadky, this->stlpce);
    else
        sucin = new Matica(matica->riadky, this->stlpce);

    return sucin;
}

int main(void)
{
    Matica *m1, *m2, *sucin;

    m1 = new Matica(3, 2);
    m2 = new Matica(2, 3);

    sucin = m1->sucin(m2);

    m1->typ();
    m2->typ();
    sucin->typ();

    return 0;
}


Unika mi nieco preco takto nie?

PS: To "overeni" je dobry kviz o CR ;)

k

Re:Násobení matic a automatické přetypování
« Odpověď #33 kdy: 17. 09. 2015, 21:09:22 »
Tak si to napiš (ve Swiftu). Jasně, je to náročné na pochopení, ale Swift to umí, funkční implementace je důkaz.

Ani na třetí pokus jste nedodal vysvětlení jak by to mělo fungovat, tedy to uzavírám s tím že neumí.

Naprasený příklad ve Scale:

Neřeší zadání, to je něco úplně jiného.

JS

Re:Násobení matic a automatické přetypování
« Odpověď #34 kdy: 17. 09. 2015, 21:12:11 »
Pravě že ne. Třetí cesta je polymorfismus návratové hodnoty (jde to ve Swiftu, jinak nevím, kde ještě).

Coz v podstate neni nic jineho nez pretypovani vysledku za behu (jak tu nekdo ukazal v Pythonu). Ale to je prave dusledek toho zmateni, o cem jsou typy.


Inkvizitor

Re:Násobení matic a automatické přetypování
« Odpověď #35 kdy: 17. 09. 2015, 22:00:13 »
Naprasený příklad ve Scale:

Neřeší zadání, to je něco úplně jiného.

Řeší problém (aby šly použít metody dávající smysl jen pro čtvercovou matici), neřeší přesnou představu (abych v takovém případě dostal instanci čtvercové matice), je ale otázka, zda zrovna na tomhle autor otázky bazíruje - doufám, že ne, protože to je podle mě docela nesmyslný požadavek. Samozřejmě, že těch možností řešení je více, třeba přes case classes, když budu chtít zůstat u Scaly a statických jazyků obecně. Dynamické jazyky, jak zde už zaznělo, nemají problém vůbec.

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #36 kdy: 17. 09. 2015, 22:01:18 »
V dynamickém jazyce to půjde vždy, to je jasné. Tady se řeší staticky typovaný jazyk.

Tak som oprasil c++

Kód: [Vybrat]
#include <iostream>

class Matica {
    protected:
        int riadky;
        int stlpce;
    public:
        Matica(int, int);
        Matica* sucin(Matica *);
        virtual void typ() { std::cout << "Matica " << this->riadky << ", " << this->stlpce << "\n"; }
};

class StvMatica: public Matica {
    public:
        StvMatica (int r, int s) : Matica (r, s) {}
        virtual void typ() { std::cout << "Stvorcova Matica " << this->riadky << ", " << this->stlpce << "\n"; }
};

Matica::Matica(int r, int s)
{
    this->riadky=r;
    this->stlpce=s;
}

Matica* Matica::sucin(Matica *matica)
{
    Matica *sucin;
    if (this->stlpce == matica->riadky)
        sucin = new StvMatica(matica->riadky, this->stlpce);
    else
        sucin = new Matica(matica->riadky, this->stlpce);

    return sucin;
}

int main(void)
{
    Matica *m1, *m2, *sucin;

    m1 = new Matica(3, 2);
    m2 = new Matica(2, 3);

    sucin = m1->sucin(m2);

    m1->typ();
    m2->typ();
    sucin->typ();

    return 0;
}


Unika mi nieco preco takto nie?

PS: To "overeni" je dobry kviz o CR ;)

To je OK, ale nejde napsat (m1*m2).trace(), vlastně jde teď jen o to, že v některých jazycích to jde bez přetypování. V C++ ale ne...

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #37 kdy: 17. 09. 2015, 22:03:11 »
Tak si to napiš (ve Swiftu). Jasně, je to náročné na pochopení, ale Swift to umí, funkční implementace je důkaz.

Ani na třetí pokus jste nedodal vysvětlení jak by to mělo fungovat, tedy to uzavírám s tím že neumí.

Naprasený příklad ve Scale:
Kód jsem psal výše, opakovat ho nebudu. Buď nevíš, co je polymorfismus, nebo návratová hodnota.

Neřeší zadání, to je něco úplně jiného.

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #38 kdy: 17. 09. 2015, 22:04:20 »
Pravě že ne. Třetí cesta je polymorfismus návratové hodnoty (jde to ve Swiftu, jinak nevím, kde ještě).

Coz v podstate neni nic jineho nez pretypovani vysledku za behu (jak tu nekdo ukazal v Pythonu). Ale to je prave dusledek toho zmateni, o cem jsou typy.
Ne za běhu, ale při kompilaci. To je pravé ten rozdíl. Viz kód výše.

JSH

Re:Násobení matic a automatické přetypování
« Odpověď #39 kdy: 17. 09. 2015, 22:13:35 »
V dynamickém jazyce to půjde vždy, to je jasné. Tady se řeší staticky typovaný jazyk.

Tak som oprasil c++

Kód: [Vybrat]
#include <iostream>

class Matica {
    protected:
        int riadky;
        int stlpce;
    public:
        Matica(int, int);
        Matica* sucin(Matica *);
        virtual void typ() { std::cout << "Matica " << this->riadky << ", " << this->stlpce << "\n"; }
};

class StvMatica: public Matica {
    public:
        StvMatica (int r, int s) : Matica (r, s) {}
        virtual void typ() { std::cout << "Stvorcova Matica " << this->riadky << ", " << this->stlpce << "\n"; }
};

Matica::Matica(int r, int s)
{
    this->riadky=r;
    this->stlpce=s;
}

Matica* Matica::sucin(Matica *matica)
{
    Matica *sucin;
    if (this->stlpce == matica->riadky)
        sucin = new StvMatica(matica->riadky, this->stlpce);
    else
        sucin = new Matica(matica->riadky, this->stlpce);

    return sucin;
}

int main(void)
{
    Matica *m1, *m2, *sucin;

    m1 = new Matica(3, 2);
    m2 = new Matica(2, 3);

    sucin = m1->sucin(m2);

    m1->typ();
    m2->typ();
    sucin->typ();

    return 0;
}


Unika mi nieco preco takto nie?

PS: To "overeni" je dobry kviz o CR ;)
Čtverec s obdélníkem z vedlejšího vlákna vrací úder? Uvědomuješ si, že pokud někdo přidá do Matica metodu resize, nebo něco podobného, tak máš dokonalou past, že?

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #40 kdy: 17. 09. 2015, 22:21:38 »
V dynamickém jazyce to půjde vždy, to je jasné. Tady se řeší staticky typovaný jazyk.

Tak som oprasil c++

Kód: [Vybrat]
#include <iostream>

class Matica {
    protected:
        int riadky;
        int stlpce;
    public:
        Matica(int, int);
        Matica* sucin(Matica *);
        virtual void typ() { std::cout << "Matica " << this->riadky << ", " << this->stlpce << "\n"; }
};

class StvMatica: public Matica {
    public:
        StvMatica (int r, int s) : Matica (r, s) {}
        virtual void typ() { std::cout << "Stvorcova Matica " << this->riadky << ", " << this->stlpce << "\n"; }
};

Matica::Matica(int r, int s)
{
    this->riadky=r;
    this->stlpce=s;
}

Matica* Matica::sucin(Matica *matica)
{
    Matica *sucin;
    if (this->stlpce == matica->riadky)
        sucin = new StvMatica(matica->riadky, this->stlpce);
    else
        sucin = new Matica(matica->riadky, this->stlpce);

    return sucin;
}

int main(void)
{
    Matica *m1, *m2, *sucin;

    m1 = new Matica(3, 2);
    m2 = new Matica(2, 3);

    sucin = m1->sucin(m2);

    m1->typ();
    m2->typ();
    sucin->typ();

    return 0;
}


Unika mi nieco preco takto nie?

PS: To "overeni" je dobry kviz o CR ;)
Čtverec s obdélníkem z vedlejšího vlákna vrací úder? Uvědomuješ si, že pokud někdo přidá do Matica metodu resize, nebo něco podobného, tak máš dokonalou past, že?

U násobení se dá předpokládat, že objekt je neměnný (vrací se nová matice).

Alt

Re:Násobení matic a automatické přetypování
« Odpověď #41 kdy: 17. 09. 2015, 22:38:53 »
Čtverec s obdélníkem z vedlejšího vlákna vrací úder? Uvědomuješ si, že pokud někdo přidá do Matica metodu resize, nebo něco podobného, tak máš dokonalou past, že?

Nechce sa mi lustit dalsie vlakno ani neviem ako tu past myslis. Napadlo ma taketo riesenie. Resize sa da riesit podobne ako sucin. Napisal som ako sa to podla mna da. Ako skolsky priklad to ujde, prakticky by som podobny problem asi riesil ako jednu triedu s testom na stvorec pre "stvorcove" metody. Ak naozaj musia byt stvorcove metody v samostatnej triede, tak potom asi radsej nejako metodu, ktora po teste ci to je stvorcova matica objekt pretypuje (co tu ale uz spominane na zaciatku myslim bolo).
Uz dlhsie v C++ neprogramujem, virtualne funckie som myslim nikdy v praxi vo finale nepouzil, teda aj ked mi niekedy po navrhu napadli, vzdy som myslim nasiel ine riesenie bez nich, ktore sa mi zdalo na konkretny pripad vhodnejsie.

k

Re:Násobení matic a automatické přetypování
« Odpověď #42 kdy: 17. 09. 2015, 22:44:28 »
Kód jsem psal výše, opakovat ho nebudu.

Pro jistotu ho tedy zopakujeme, aby bylo všem jasno že takhle to nejde:
Kód: [Vybrat]
func *(m1:Matrix,m2:Matrix)->Matrix
func *(m1:Matrix,m2:Matrix)->SquareMatrix

Řeší problém

... stejně idiotsky jako pokusit se přetypovat výsledek a čekat zda se nestane ClassCastException.

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #43 kdy: 17. 09. 2015, 22:54:46 »
Kód jsem psal výše, opakovat ho nebudu.

Pro jistotu ho tedy zopakujeme, aby bylo všem jasno že takhle to nejde:
Kód: [Vybrat]
func *(m1:Matrix,m2:Matrix)->Matrix
func *(m1:Matrix,m2:Matrix)->SquareMatrix

Řeší problém

... stejně idiotsky jako pokusit se přetypovat výsledek a čekat zda se nestane ClassCastException.

Tak ať v tom mám jasno - co hlásí překladač? Pokud nic, kde je přetypování? Buď máš jinou verzi překladače, nebo jen plácáš. Nebo nevíš, co je přetypování. Doporučuju manuál ke Swiftu, sekci o inferenci typů. Jsou tam ostatně podobné příklady.

k

Re:Násobení matic a automatické přetypování
« Odpověď #44 kdy: 17. 09. 2015, 23:03:24 »
Tak ať v tom mám jasno - co hlásí překladač? Pokud nic, kde je přetypování? Buď máš jinou verzi překladače, nebo jen plácáš. Nebo nevíš, co je přetypování. Doporučuju manuál ke Swiftu, sekci o inferenci typů. Jsou tam ostatně podobné příklady.

Nemá to cenu, jako u blbečků na dvorečku. Jdu dělat něco jiného.