Pomysł na rozszerzenie OOP

1

SZOK! BIERNACKI MIAŻDŻY OOP! SPOŁECZNOŚĆ 4P OBURZONA! MODERATORZY WSTRZĄŚNIĘCI!

(Miałem zamiar dać taki tytuł wątku, bo ja jestem słaby z marketingu i jak pisałem o tym pomyśle w wątku o Chomiku to nikt nie odpowiedział. Ale teraz mam trochę kodu, więc pokażę co mi chodzi po głowie na przykładzie).

Na link jest taki prototyp systemu ekspertowego napisany przeze mnie w Chomiku (wymaga najnowszego Chomika!). Najpierw trzeba skonfigurować (./configure), uruchamia się przez make run.

Źródła są w katalogu main/. Skłąda się na nie engine*.chomik i domain_knowledge.chomik. W domain_knowledge.chomik jest opisana w tym systemie klasyczna sytuacja gdzie stosujemy twierdzenie Pitagorasa.

Teraz o OOP:

Mój pomysł polega na tym, że klasy istnieją, owszem, ale tylko tak jak enumy, to znaczy mają tożsamość. To samo obiekty, liczby rzeczywiste, liczby całkowite itd. Na początek tworzymy obiekty: ABC (trójkąt), odcinki AB, BC, CA, oraz liczby rzeczywiste "real zero", "real one", "length of AB", "length of BC", "length of CA". Obiekty, liczby rzeczywiste, całkowite, boolowskie, teksty i kody są opisane faktami. Fakty nie są obiektami!

Istnieje kilka "stopni" egzystencji obiektu. Obiekt może być nazwany, zdefiniowany, istniejący, konstruowalny, konstruowalny realistycznie (przy dostępnych zasobach), znany. Możemy mieć dobrze zdefiniowane i istniejące obiekty, które nie tylko nie są konstruowalne, ale mamy dowód na to, że nie da się ich skonstruować (twierdzenie o nierozstrzygalności).

W toku dalszej pracy program tworzy pojęcia oparte na klasach (trochę tak jakby były funkcjami), na przykład samodzielnie tworzy:

square ( real zero )  is known to exist: false 
square root ( real zero )  is known to exist: false 
square ( real one )  is known to exist: false 
square root ( real one )  is known to exist: false 
square ( length of AB )  is known to exist: false 
square root ( length of AB )  is known to exist: false 
square ( length of BC )  is known to exist: false 
square root ( length of BC )  is known to exist: false 
square ( length of CA )  is known to exist: false 
square root ( length of CA )  is known to exist: false 
sum ( real zero , real zero )  is known to exist: false 
sum ( real zero , real one )  is known to exist: false 
sum ( real zero , length of AB )  is known to exist: false 
sum ( real zero , length of BC )  is known to exist: false 
sum ( real zero , length of CA )  is known to exist: false 
sum ( real one , real zero )  is known to exist: false 
sum ( real one , real one )  is known to exist: false 
sum ( real one , length of AB )  is known to exist: false 
sum ( real one , length of BC )  is known to exist: false 
sum ( real one , length of CA )  is known to exist: false 
sum ( length of AB , real zero )  is known to exist: false 
sum ( length of AB , real one )  is known to exist: false 
sum ( length of AB , length of AB )  is known to exist: false 
sum ( length of AB , length of BC )  is known to exist: false 
sum ( length of AB , length of CA )  is known to exist: false 
sum ( length of BC , real zero )  is known to exist: false 
sum ( length of BC , real one )  is known to exist: false 
sum ( length of BC , length of AB )  is known to exist: false 
sum ( length of BC , length of BC )  is known to exist: false 
sum ( length of BC , length of CA )  is known to exist: false 
sum ( length of CA , real zero )  is known to exist: false 
sum ( length of CA , real one )  is known to exist: false 
sum ( length of CA , length of AB )  is known to exist: false 
sum ( length of CA , length of BC )  is known to exist: false 
sum ( length of CA , length of CA )  is known to exist: false 

No i w następnej iteracji jeżeli dojdzie do tego, że np. "square ( length of AB)" istnieje i "square(length of BC)" istnieje, to utworzy pojęcie (nowy obiekt) "sum(square ( length of AB), square ( length of BC))". Czyli klasy działają trochę jak konstruktory w OOP. Mam nadzieję doprowadzić go do stanu, w którym zauważy, że dwa obiekty zdefiniowane automatycznie (tj. nie w domain_knowledge.chomik) są sobie równe i wyprowadzić metodę konstrukcji "length of CA".

Różni się to od OOP tym, że obiekty nie są utożsamiane z krotkami atrybutów, tylko każdy obiekt ma po prostu tożsamość, podobnie jak liczba rzeczywista czy inna, albo tekst. Poza tym obiekty mogą istnieć i być konstruowalne, ale nie realistycznie konstruowalne (tak jak np. rozwinięcie dziesiętne liczby PI). Albo istnieć i nie być konstruowalne. Albo mieć nazwę i definicję, ale nie istnieć (jak np. liczba X mniejsza od 0 i jednocześnie większa od 5). W sumie programista może w tym systemie zbliżyć się bardziej do matematyki niż w tradycyjnym OOP.

I pytanie - co o tym sądzicie.

2

To mi przypomina jak kiedyś czytałem o języku Prolog, tam się robiło podobne fakty (nigdy w tym nie programowałem, tylko wiem, że coś takiego istnieje).
https://en.wikipedia.org/wiki/Prolog

Mój pomysł polega na tym, że klasy istnieją, owszem, ale tylko tak jak enumy, to znaczy mają tożsamość. To samo obiekty, liczby rzeczywiste, liczby całkowite itd.

Coś mi się widzi, że mógłbyś się zainteresować nieco bardziej abstrakcyjną matmą np. teorią kategorii. O ile jeszcze się nie interesujesz.

1

Zgadzam się z @LukeJL , przypomina to programowanie w logice. Ale tym bardziej nie czaję, po co uwikływać w to programowanie obiektowe? To zdaje się być zupełnie inny paradygmat.

2

@Paweł Biernacki: gratulacje, właśnie odkryłeś programowanie logiczne: https://pl.m.wikipedia.org/wiki/Programowanie_logiczne

Czyli nie OOP.

0

@LukeJL - masz rację, to jest trochę związane z Prologiem. (Znam i używam SWI Prolog). Poczytałęm trochę o teorii kategorii - ciekawe. Słyszałem o tym, ale nie wiedziałem. Dzięki.

@enedil - Zgadzam się. Mam nadzieję na zrobienie czegoś lepszego niż programowanie obiektowe, potrzebne mi jest tylko jako punkt odniesienia. To istotnie jest inny paradygmat, trochę bliższy matematyki, moim zdaniem. Na przykłąd w OOP są trudności z pojęciem tożsamości i równości obiektów (czy dwie różne instancje o tych samych wartościach atrybutów to ten sam obiekt czy dwa różne). Ponadto kwestia istnienia i konstruowalności nie istnieje w OOP, a to ważne kwestie.

@wartek01 - Dzięki za gratulacje, ale chyba jestem bliżej OOP, tylko jakby poprawionego. Wydaje mi się, że programowanie logiczne jest trochę zbyt wąskie w porównaniu z tym, co proponuję.

Chciałem pokazać, że w Chomiku staje się możliwe zaimplementowanie czegoś silniejszego niż OOP. To znaczy bliższego matematyki, bardziej użytecznego. Nie wspomniałem o Prologu - ale może przyszedł czas, żeby to zrobić. W Prologu mamy bazę wiedzy opisywaną w kategoriach faktów i reguł, niepotrzebnie miesza się np. wartość zmiennej z wiedzą na jej temat - np. przez predykat MA_WARTOSC(ZMIENNA, WARTOSC) obok predykatu JEST_SUMA(ZMIENNA,ZMIENNA1,ZMIENNA2). Można by oczywiście taki system ekspertowy zrobić i w Prologu, w końcu Chomik jest napisany w C++ i nie ma w nim żadnej magii. Chomik daje tylko pewną przewagę jeśli chodzi o reprezentację wiedzy, zwłaszcza ujednolicenie i wieloczłonowość nazw zmiennych. Sercem tego systemu (Esc) jest engine.chomik (linie 16-194), w których wykorzystuję rekurencyjne typy wyliczeniowe.

5
  1. Jak patrzę na ten kod nic nie rozumiem, ale widzę pewną inspirację COBOLem. Nie wiem czy to dobrze wróży xD.
  2. Rozumiem chęć zaimplementowania Prologu jeszcze raz, bo jego implementacje są dość słabe. :)
  3. Na twoim miejscu, zanim zabrałbym za tworzenie się nowych języków, poznałbym najpierw Lispa, Haskella i Idrisa, bo odnoszę wrażenie, że kontakt z programowaniem masz tylko w pracy gdzie programowanie jest archaiczne.
0
elwis napisał(a):
  1. Jak patrzę na ten kod nic nie rozumiem, ale widzę pewną inspirację COBOLem. Nie wiem czy to dobrze wróży xD.
  2. Rozumiem chęć zaimplementowania Prologu jeszcze raz, bo jego implementacje są dość słabe. :)
  3. Na twoim miejscu, zanim zabrałbym za tworzenie się nowych języków, poznałbym najpierw Lispa, Haskella i Idrisa, bo odnoszę wrażenie, że kontakt z programowaniem masz tylko w pracy gdzie programowanie jest archaiczne (OOP, wzorce projektowe i inne takie przedszkolne zabawy).
  1. Nie znam COBOLa, trudno mówić o inspiracji. Do zrozumienia Chomika polecam tutorial link
  2. Nie mam takich ambicji. Chomik jest imperatywnym językiem programowania.
  3. Rozumiem. Uczyłem się Haskella, ale nie nauczyłem się go. Lispa trochę liznąłem, dokładnie Scheme (potrzebowałem do Gimpa). Idrisa nie znam. Moje języki to C++, Java, Perl, Python, SWI Prolog.

Masz rację, że programowanie w przemyśle bywa archaiczne. W tym wątku proponuję pewne rozszerzenie OOP o wspieranie pojęć takich jak istnienie, równość, konstruowalność. Sam Chomik tego nie wspiera, ale dzięki rekurencyjnym typom wyliczeniowym można to w nim napisać. Czymś takim jest właśnie Esc.

Myślisz, że Chomik traci na tym, że nie znam Haskella? Albo Lispa? A dlaczego? Mnie się bardzo podoba, to imperatywny język bez instrukcji pętli (jawnej) i bez instrukcji warunkowej. A mimo to bardzo silny. Może jako jego twórca nie jestem obiektywny, mam 50 lat i będąc seniorem mam swoje ego ;))) Ale odnośnie pracy - z ostatniej pracy mnie wywalili po okresie próbnym (w czerwcu 2023). Programuję raczej w domu, przynajmniej teraz. Ale zgadza się, że w C++, no, teraz w Chomiku.

1

Sugeruję Lispa i Haskella, żeby pokazać w jakim kierunku idze tworzenie języków programowania i nie jest to zdecydowanie OOP. Ty natomiast masz problem i chcesz to rozwiązać tworząc autorskie usprawnienie OOP, podczas gdy nauczenie się bardziej zaawansowanego języka mogłoby rozwiązać jeszcze kilka kolejnych, z których nie zdajesz sobie sprawę. To tylko uwaga na marginesie. Wiem jak to jest mieć nieodpartą ochotę stworzenia języka programowania. :D

0

Nie gniewam się o uwagę na marginesie - moje ego nie jest aż tak duże ;))) Haskell mi się dość podobał, ale to tylko próba stworzenia z funkcji "first-class-citizen", wszędzie operujemy na funkcjach. Haskell jest zapewne bardziej zaawansowany niż Chomik (Chomika zacząłem pisać w kwietniu 2023), ale jeśli chodzi o enumy czyli tzw. typy wyliczeniowe Haskell jest od Chomika dużo słabszy.

Może pokażę to na przykładzie: po odpaleniu poniższego kodu w Chomiku:

type person={Gotrek, Gwaigilion, Gerrudir}, place={Krakow, Warszawa, Wroclaw, Poznan, Gdansk};
type information={(X:person) is in (Y:place), (X:person) has told (Y:person) that (I:information), (X:person) has done (A:action)};
type action={tell (X:person) that (I:information), go to (X:place)};
expand(3);
<print (I:information)>;

... otrzymamy listę:

GotrekisinKrakow 
GotrekisinWarszawa 
GotrekisinWroclaw 
GotrekisinPoznan 
GotrekisinGdansk 
GwaigilionisinKrakow 
GwaigilionisinWarszawa 
GwaigilionisinWroclaw 
GwaigilionisinPoznan 
GwaigilionisinGdansk 
GerrudirisinKrakow 
GerrudirisinWarszawa 
GerrudirisinWroclaw 
GerrudirisinPoznan 
GerrudirisinGdansk 
GotrekhastoldGotrekthatGotrekisinKrakow 
GotrekhastoldGotrekthatGotrekisinWarszawa 
GotrekhastoldGotrekthatGotrekisinWroclaw 
GotrekhastoldGotrekthatGotrekisinPoznan 
GotrekhastoldGotrekthatGotrekisinGdansk 
GotrekhastoldGotrekthatGwaigilionisinKrakow 
GotrekhastoldGotrekthatGwaigilionisinWarszawa 
GotrekhastoldGotrekthatGwaigilionisinWroclaw 
GotrekhastoldGotrekthatGwaigilionisinPoznan 
GotrekhastoldGotrekthatGwaigilionisinGdansk 
GotrekhastoldGotrekthatGerrudirisinKrakow 
GotrekhastoldGotrekthatGerrudirisinWarszawa 
GotrekhastoldGotrekthatGerrudirisinWroclaw 
GotrekhastoldGotrekthatGerrudirisinPoznan 
GotrekhastoldGotrekthatGerrudirisinGdansk 
GotrekhastoldGwaigilionthatGotrekisinKrakow 
GotrekhastoldGwaigilionthatGotrekisinWarszawa 
GotrekhastoldGwaigilionthatGotrekisinWroclaw 
GotrekhastoldGwaigilionthatGotrekisinPoznan 
GotrekhastoldGwaigilionthatGotrekisinGdansk 
GotrekhastoldGwaigilionthatGwaigilionisinKrakow 
GotrekhastoldGwaigilionthatGwaigilionisinWarszawa 
GotrekhastoldGwaigilionthatGwaigilionisinWroclaw 
GotrekhastoldGwaigilionthatGwaigilionisinPoznan 
GotrekhastoldGwaigilionthatGwaigilionisinGdansk 
GotrekhastoldGwaigilionthatGerrudirisinKrakow 
GotrekhastoldGwaigilionthatGerrudirisinWarszawa 
GotrekhastoldGwaigilionthatGerrudirisinWroclaw 
GotrekhastoldGwaigilionthatGerrudirisinPoznan 
GotrekhastoldGwaigilionthatGerrudirisinGdansk 
GotrekhastoldGerrudirthatGotrekisinKrakow 
GotrekhastoldGerrudirthatGotrekisinWarszawa 
GotrekhastoldGerrudirthatGotrekisinWroclaw 
GotrekhastoldGerrudirthatGotrekisinPoznan 
GotrekhastoldGerrudirthatGotrekisinGdansk 
GotrekhastoldGerrudirthatGwaigilionisinKrakow 
GotrekhastoldGerrudirthatGwaigilionisinWarszawa 
GotrekhastoldGerrudirthatGwaigilionisinWroclaw 
GotrekhastoldGerrudirthatGwaigilionisinPoznan 
GotrekhastoldGerrudirthatGwaigilionisinGdansk 
GotrekhastoldGerrudirthatGerrudirisinKrakow 
GotrekhastoldGerrudirthatGerrudirisinWarszawa 
GotrekhastoldGerrudirthatGerrudirisinWroclaw 
GotrekhastoldGerrudirthatGerrudirisinPoznan 
GotrekhastoldGerrudirthatGerrudirisinGdansk 
GwaigilionhastoldGotrekthatGotrekisinKrakow 
GwaigilionhastoldGotrekthatGotrekisinWarszawa 
GwaigilionhastoldGotrekthatGotrekisinWroclaw 
GwaigilionhastoldGotrekthatGotrekisinPoznan 
GwaigilionhastoldGotrekthatGotrekisinGdansk 
GwaigilionhastoldGotrekthatGwaigilionisinKrakow 
GwaigilionhastoldGotrekthatGwaigilionisinWarszawa 
GwaigilionhastoldGotrekthatGwaigilionisinWroclaw 
GwaigilionhastoldGotrekthatGwaigilionisinPoznan 
GwaigilionhastoldGotrekthatGwaigilionisinGdansk 
GwaigilionhastoldGotrekthatGerrudirisinKrakow 
GwaigilionhastoldGotrekthatGerrudirisinWarszawa 
GwaigilionhastoldGotrekthatGerrudirisinWroclaw 
GwaigilionhastoldGotrekthatGerrudirisinPoznan 
GwaigilionhastoldGotrekthatGerrudirisinGdansk 
GwaigilionhastoldGwaigilionthatGotrekisinKrakow 
GwaigilionhastoldGwaigilionthatGotrekisinWarszawa 
GwaigilionhastoldGwaigilionthatGotrekisinWroclaw 
GwaigilionhastoldGwaigilionthatGotrekisinPoznan 
GwaigilionhastoldGwaigilionthatGotrekisinGdansk 
GwaigilionhastoldGwaigilionthatGwaigilionisinKrakow 
GwaigilionhastoldGwaigilionthatGwaigilionisinWarszawa 
GwaigilionhastoldGwaigilionthatGwaigilionisinWroclaw 
GwaigilionhastoldGwaigilionthatGwaigilionisinPoznan 
GwaigilionhastoldGwaigilionthatGwaigilionisinGdansk 
GwaigilionhastoldGwaigilionthatGerrudirisinKrakow 
GwaigilionhastoldGwaigilionthatGerrudirisinWarszawa 
GwaigilionhastoldGwaigilionthatGerrudirisinWroclaw 
GwaigilionhastoldGwaigilionthatGerrudirisinPoznan 
GwaigilionhastoldGwaigilionthatGerrudirisinGdansk 
GwaigilionhastoldGerrudirthatGotrekisinKrakow 
GwaigilionhastoldGerrudirthatGotrekisinWarszawa 
GwaigilionhastoldGerrudirthatGotrekisinWroclaw 
GwaigilionhastoldGerrudirthatGotrekisinPoznan 
GwaigilionhastoldGerrudirthatGotrekisinGdansk 
GwaigilionhastoldGerrudirthatGwaigilionisinKrakow 
GwaigilionhastoldGerrudirthatGwaigilionisinWarszawa 
GwaigilionhastoldGerrudirthatGwaigilionisinWroclaw 
GwaigilionhastoldGerrudirthatGwaigilionisinPoznan 
GwaigilionhastoldGerrudirthatGwaigilionisinGdansk 
GwaigilionhastoldGerrudirthatGerrudirisinKrakow 
GwaigilionhastoldGerrudirthatGerrudirisinWarszawa 
GwaigilionhastoldGerrudirthatGerrudirisinWroclaw 
GwaigilionhastoldGerrudirthatGerrudirisinPoznan 
GwaigilionhastoldGerrudirthatGerrudirisinGdansk 
GerrudirhastoldGotrekthatGotrekisinKrakow 
GerrudirhastoldGotrekthatGotrekisinWarszawa 
GerrudirhastoldGotrekthatGotrekisinWroclaw 
GerrudirhastoldGotrekthatGotrekisinPoznan 
GerrudirhastoldGotrekthatGotrekisinGdansk 
GerrudirhastoldGotrekthatGwaigilionisinKrakow 
GerrudirhastoldGotrekthatGwaigilionisinWarszawa 
GerrudirhastoldGotrekthatGwaigilionisinWroclaw 
GerrudirhastoldGotrekthatGwaigilionisinPoznan 
GerrudirhastoldGotrekthatGwaigilionisinGdansk 
GerrudirhastoldGotrekthatGerrudirisinKrakow 
GerrudirhastoldGotrekthatGerrudirisinWarszawa 
GerrudirhastoldGotrekthatGerrudirisinWroclaw 
GerrudirhastoldGotrekthatGerrudirisinPoznan 
GerrudirhastoldGotrekthatGerrudirisinGdansk 
GerrudirhastoldGwaigilionthatGotrekisinKrakow 
GerrudirhastoldGwaigilionthatGotrekisinWarszawa 
GerrudirhastoldGwaigilionthatGotrekisinWroclaw 
GerrudirhastoldGwaigilionthatGotrekisinPoznan 
GerrudirhastoldGwaigilionthatGotrekisinGdansk 
GerrudirhastoldGwaigilionthatGwaigilionisinKrakow 
GerrudirhastoldGwaigilionthatGwaigilionisinWarszawa 
GerrudirhastoldGwaigilionthatGwaigilionisinWroclaw 
GerrudirhastoldGwaigilionthatGwaigilionisinPoznan 
GerrudirhastoldGwaigilionthatGwaigilionisinGdansk 
GerrudirhastoldGwaigilionthatGerrudirisinKrakow 
GerrudirhastoldGwaigilionthatGerrudirisinWarszawa 
GerrudirhastoldGwaigilionthatGerrudirisinWroclaw 
GerrudirhastoldGwaigilionthatGerrudirisinPoznan 
GerrudirhastoldGwaigilionthatGerrudirisinGdansk 
GerrudirhastoldGerrudirthatGotrekisinKrakow 
GerrudirhastoldGerrudirthatGotrekisinWarszawa 
GerrudirhastoldGerrudirthatGotrekisinWroclaw 
GerrudirhastoldGerrudirthatGotrekisinPoznan 
GerrudirhastoldGerrudirthatGotrekisinGdansk 
GerrudirhastoldGerrudirthatGwaigilionisinKrakow 
GerrudirhastoldGerrudirthatGwaigilionisinWarszawa 
GerrudirhastoldGerrudirthatGwaigilionisinWroclaw 
GerrudirhastoldGerrudirthatGwaigilionisinPoznan 
GerrudirhastoldGerrudirthatGwaigilionisinGdansk 
GerrudirhastoldGerrudirthatGerrudirisinKrakow 
GerrudirhastoldGerrudirthatGerrudirisinWarszawa 
GerrudirhastoldGerrudirthatGerrudirisinWroclaw 
GerrudirhastoldGerrudirthatGerrudirisinPoznan 
GerrudirhastoldGerrudirthatGerrudirisinGdansk 
GotrekhasdonegotoKrakow 
GotrekhasdonegotoWarszawa 
GotrekhasdonegotoWroclaw 
GotrekhasdonegotoPoznan 
GotrekhasdonegotoGdansk 
GwaigilionhasdonegotoKrakow 
GwaigilionhasdonegotoWarszawa 
GwaigilionhasdonegotoWroclaw 
GwaigilionhasdonegotoPoznan 
GwaigilionhasdonegotoGdansk 
GerrudirhasdonegotoKrakow 
GerrudirhasdonegotoWarszawa 
GerrudirhasdonegotoWroclaw 
GerrudirhasdonegotoPoznan 
GerrudirhasdonegotoGdansk 

Tymczasem w Haskellu istnieje tylko stare, poczciwe wyliczenie wartości,

data Rank =
      Rank2
    | Rank3
    | Rank4
    | Rank5
    | Rank6
    | Rank7
    | Rank8
    | Rank9
    | Rank10
    | Jack
    | Queen
    | King
    | Ace
    deriving (Bounded, Enum, Show)

Podejrzewam, że z Lispem jest tak samo. Reasumując, jeżeli wszyscy są innego zdania niż ja, to znaczy, że wszyscy się mylą ;))) Może być, że współczesne języki programowania idą w innym kierunku niż OOP. Nawet innym niż moje OOP (nie mam nazwy, może CHomik OOP, czyli CHOOP). W takim wypadku rozważę jeszcze swoją opinię, ale skłonny jestem przypuszczać, że z tego wynika iż współczesne języki programowania idą w złym kierunku. Niemniej jednak gdybym miał pisać skrypt sięgnąłbym po Perla, ewentualnie Pytona (na razie jeszcze nie Chomika).

0

OOP masz wtedy jak dane i kod są integralnie połączone. Np. dane są obwarowane enkapsulacją i mogą być zarządzane tylko przez metody albo metody mogą być wołane tylko na obiektach. U ciebie jest zwykłe programowanie logiczne i lużne połączenie pomiędzy jednym a drugim

1

Przykład, który pokazałeś można spokojnie zrobić na typie algebraicznym. Żeby nie rozwlekać za bardzo:

data Information = IsIn Person Place
                 | ToldThat Person Information
                 | HasDone Person Action

Typy Person, Place i Action pewnie musiałyby już być jakimiś kolekcjami, żeby dało się je dodawać w czasie wykonywania…

W Lispie to już wchodzi metaprogramowanie, luźno da się zaimplementować coś takiego (przynajmniej w CommonLispie). Nawet dokładnie taką składnie jaką proponujesz. :D

0
slsy napisał(a):

OOP masz wtedy jak dane i kod są integralnie połączone. Np. dane są obwarowane enkapsulacją i mogą być zarządzane tylko przez metody albo metody mogą być wołane tylko na obiektach. U ciebie jest zwykłe programowanie logiczne i lużne połączenie pomiędzy jednym a drugim

Prawda. U mnie nie ma enkapsulacji.

Ale to nic nie szkodzi, że nie ma. Jest coś lepszego - w Chomiku kod jest zwykłym wbudowanym typem, tyle, że można go wykonać. To podejście do kodu w każdym języku (że niby oddzielnie kod oddzielnie dane) jest sprzeczne z filozofią Chomika. Gdybym chciał mógłbym zrobić operacje na zmiennych typu code.

Ciekawostka (jeden z testów chomika - test22.chomik):


<create new output stringstream>;
let my index = <the created stream index>;

let the print target stream index = <my index>;
let the print separator = value string "";
let the print end of line = value string "";

variable abc (X:code):code;
let abc (X:code)=value code
{
    let x = value code [(X:code)];
    <print "hello">;
    <x>;
    <x>;
};

<abc {<print "bye">;}>; ###################### <<<<<< wypisze "hellobyebye"

let the print separator = value string " ";
let the print end of line = value string "\n";
let the print target stream index = value integer 0;

let the get from stream stream index = <my index>;
<get from stream>;
<print "RESULT:" <the get from stream result>>;

Ten kod w Chomiku "wstrzykuje" poniekąd kod tak jakby był parametrem. Fajnie, nie?

0
elwis napisał(a):

Przykład, który pokazałeś można spokojnie zrobić na typie algebraicznym. Żeby nie rozwlekać za bardzo:

data Information = IsIn Person Place
                 | ToldThat Person Information
                 | HasDone Person Action

Typy Person, Place i Action pewnie musiałyby już być jakimiś kolekcjami, żeby dało się je dodawać w czasie wykonywania…

W Lispie to już wchodzi metaprogramowanie, luźno da się zaimplementować coś takiego (przynajmniej w CommonLispie). Nawet dokładnie taką składnie jaką proponujesz. :D

Ha! Złapałeś mnie! Nie wiedziałem, że Haskell też tak umie. Sprytny język. Ale u mnie Action nie jest kolekcją, i zauważ, że informacja (jedna z możliwych) zależy od akcji, a akcja zależy od informacji! Mam tylko pewne ograniczenie głębokości rekurencji (przekazane jako parametr do expand).

(X:person) has done (A:action) # tutaj informacja zależy od akcji

tell (X:person) that (I:information) # a tutaj akcja zależy od informacji

To jak, jest Chomik silniejszy? Czy nie jest?

2
tell info whom what = info + KnowsThat whom what
hasDone info who what = info + HasDone who what

Tylko należałoby dodać konstruktor KnowsThat do typu information.

To co obserwuję, to dodanie jednego hacku, pozwalającego zaimplementować jedną rzecz. Typowymi zlepkami takich hacków są np C++ i Perl. Widzieliśmy ich dostatecznie dużo, żeby stwierdzić, że są to znacznie dalej idące wzorce i o tym generalnie jest FP.

0
elwis napisał(a):
tell info whom what = info + KnowsThat whom what
hasDone info who what = info + HasDone who what

Tylko należałoby dodać konstruktor KnowsThat do typu information.

To co obserwuję, to dodanie jednego hacku, pozwalającego zaimplementować jedną rzecz. Typowymi zlepkami takich hacków są np C++ i Perl. Widzieliśmy ich dostatecznie dużo, żeby stwierdzić, że są to znacznie dalej idące wzorce i o tym generalnie jest FP.

To prawda, te moje typy wyliczeniowe nie są całkiem czyste. Lepiej by było, gdybym mógł tam użyć jeszcze typów nieskończonych, albo nieskończenie głębokiej rekurencji a nie mogę.

Ale nie wiń Chomika za grzechy Perla czy C++, to nie po chrześcijańsku ;))) Niestety jak chodzi o wiarę to sam jestem człowiekiem małej wiary i dopóki nie zobaczę, że FP jest lepsze, to nie uwierzę. Wydaje mi się, że FP wynika z dobrych intencji. Tak rozumiem sprowadzenie funkcji do roli zwykłych "atomów". Ja poniekąd też mam coś takiego - nazywam to typem "code". Ale i tu Chomik jest lepszy - bo code jest zwykłym wbudowanym typem i można by zrobić coś takiego:

variable x:code;
let x = value code { <print "alpha">; };
<x>
let x = value code { <print "beta">; };
<x>

To wypisze raz alpha a raz beta. Mam zmienne typu code.

Więc jak mówię, intencje twórców Haskella były zacne, ale chyba FP nie będzie miało szans z CHOOP. Wyobraź sobie program, który może zapytać (o dowolnie zdefiniowany obiekt), czy on istnieje. Czy da się go skonstruować? Czy da się go skonstruować w rozsądnym czasie? Albo może, czy da się udowodnić, że konstrukcja jest niemożliwa? Zdefiniuje sobie kod konstruujący dany obiekt i sprawdzi, czy któryś z kodów, którymi dysponuje ma szansę takiej konstrukcji dokonać. Albo zdefiniuje sobie człowieka (obiekt), który dysponuje żądaną informacją i zapyta, czy taki człowiek istnieje. Albo nawet (strach powiedzieć) czy dałoby się sztucznie go skonstruować.

1
Paweł Biernacki napisał(a):

Ale nie wiń Chomika za grzechy Perla czy C++, to nie po chrześcijańsku ;))) Niestety jak chodzi o wiarę to sam jestem człowiekiem małej wiary i dopóki nie zobaczę, że FP jest lepsze, to nie uwierzę. Wydaje mi się, że FP wynika z dobrych intencji. Tak rozumiem sprowadzenie funkcji do roli zwykłych "atomów". Ja poniekąd też mam coś takiego - nazywam to typem "code". Ale i tu Chomik jest lepszy - bo code jest zwykłym wbudowanym typem i można by zrobić coś takiego:

Ja tam nikogo o nic nie winię. Stwierdzam fakt, że na ogół dobrze nam wychodzi robienie doraźnych hacków, a dopiero z czasem przychodzi robienie uogólnionych abstrakcji. Tylko tyle, że C++ i perl to lata 90te (kiedy dorastały :D), a mamy lata 20e kolejnego wieku. Moim zdaniem wciąż wymyślać doraźne rowiązania na problemy dla których są już rozwiązania ogólne.

variable x:code;
let x = value code { <print "alpha">; };
<x>
let x = value code { <print "beta">; };
<x>

To wypisze raz alpha a raz beta. Mam zmienne typu code.

Wygląda jak zwyczajne używanie funkcji jako wartości, nie wiem co w tym innowacyjnego. Praktycznie każdy nowoczesny język to umie, nawet Perl:

my $x = sub { print "alpha\n" };
$x->();

$x = sub { print "beta\n" };
$x->();

Więc jak mówię, intencje twórców Haskella były zacne, ale chyba FP nie będzie miało szans z CHOOP. Wyobraź sobie program, który może zapytać (o dowolnie zdefiniowany obiekt), czy on istnieje. Czy da się go skonstruować? Czy da się go skonstruować w rozsądnym czasie? Albo może, czy da się udowodnić, że konstrukcja jest niemożliwa? Zdefiniuje sobie kod konstruujący dany obiekt i sprawdzi, czy któryś z kodów, którymi dysponuje ma szansę takiej konstrukcji dokonać. Albo zdefiniuje sobie człowieka (obiekt), który dysponuje żądaną informacją i zapyta, czy taki człowiek istnieje. Albo nawet (strach powiedzieć) czy dałoby się sztucznie go skonstruować.

Program, który może zapytać o dowolnie zdefiniowany obiekt. Pytanie właściwie po co? Żeby to mogło działać, to musiałby być dynamiczny język (a zatem pewne kompromisy wydajnościowe). W Lispie da się to zaimplementować. Tylko w zasadzie po co? Opisujemy obiekty poprzez cechy (trait/interface/type class). Jeśli typ implementuje cechę, można go użyć w danym miejscu. Krótka piłka.
Co do dowodzenia, to ile wiem, Idris zapewnia dość rozbudowane możliwości formalnego udowadniania twierdzeń na temat kodu. Tutaj to już w ogóle przydają się typy z parametrem (wartość, nie inny typ; np. rozmiar kolekcji).

0
elwis napisał(a):
Paweł Biernacki napisał(a):

Ale nie wiń Chomika za grzechy Perla czy C++, to nie po chrześcijańsku ;))) Niestety jak chodzi o wiarę to sam jestem człowiekiem małej wiary i dopóki nie zobaczę, że FP jest lepsze, to nie uwierzę. Wydaje mi się, że FP wynika z dobrych intencji. Tak rozumiem sprowadzenie funkcji do roli zwykłych "atomów". Ja poniekąd też mam coś takiego - nazywam to typem "code". Ale i tu Chomik jest lepszy - bo code jest zwykłym wbudowanym typem i można by zrobić coś takiego:

Ja tam nikogo o nic nie winię. Stwierdzam fakt, że na ogół dobrze nam wychodzi robienie doraźnych hacków, a dopiero z czasem przychodzi robienie uogólnionych abstrakcji. Tylko tyle, że C++ i perl to lata 90te (kiedy dorastały :D), a mamy lata 20e kolejnego wieku. Moim zdaniem wciąż wymyślać doraźne rowiązania na problemy dla których są już rozwiązania ogólne.

Zgadzam się z Twoim stwierdzeniem, że robienie doraźnych hacków jest łatwiejsze. I zgadzam się, że C++ i Perl były, jak na tamte lata, bardzo nowoczesne. Ja ich zresztą do dzisiaj używam.

Ale nie zgadzam się z sugestią, że Esc (albo Chomik) to doraźne rozwiązanie problemów, dla których są rozwiązania ogólne. Po pierwsze chomik jest bardzo ogólny, a po drugie istnieje cała klasa problemów, które w Chomiku można rozwiązać najłatwiej (można oczywiście i w C++, w końcu Chomik jest w nim napisany). Ponieważ stawiasz kwestię "po co" to robić - odpowiem poniżej, jakie to problemy.

variable x:code;
let x = value code { <print "alpha">; };
<x>
let x = value code { <print "beta">; };
<x>

To wypisze raz alpha a raz beta. Mam zmienne typu code.

Wygląda jak zwyczajne używanie funkcji jako wartości, nie wiem co w tym innowacyjnego. Praktycznie każdy nowoczesny język to umie, nawet Perl:

my $x = sub { print "alpha\n" };
$x->();

$x = sub { print "beta\n" };
$x->();

Tak, tak właśnie jest, z pojawieniem się closures i lambd to stało się możliwe. Ale closures czy lambdy to raczej wyjątek od reguły, a u mnie reguła. Może to nie jest bardzo innowacyjne, ale jest lepsze niż ten święty podział na dane i kod, który jest nawet w OOP, pod nazwą enkapsulacji.

Więc jak mówię, intencje twórców Haskella były zacne, ale chyba FP nie będzie miało szans z CHOOP. Wyobraź sobie program, który może zapytać (o dowolnie zdefiniowany obiekt), czy on istnieje. Czy da się go skonstruować? Czy da się go skonstruować w rozsądnym czasie? Albo może, czy da się udowodnić, że konstrukcja jest niemożliwa? Zdefiniuje sobie kod konstruujący dany obiekt i sprawdzi, czy któryś z kodów, którymi dysponuje ma szansę takiej konstrukcji dokonać. Albo zdefiniuje sobie człowieka (obiekt), który dysponuje żądaną informacją i zapyta, czy taki człowiek istnieje. Albo nawet (strach powiedzieć) czy dałoby się sztucznie go skonstruować.

Program, który może zapytać o dowolnie zdefiniowany obiekt. Pytanie właściwie po co? Żeby to mogło działać, to musiałby być dynamiczny język (a zatem pewne kompromisy wydajnościowe). W Lispie da się to zaimplementować. Tylko w zasadzie po co?

W każdym dostatecznie silnym języku, czyli w każdym języku programowania ogólnego przeznaczenia, dałoby się zaimplementować Chomika, a więc i Esc.

PO CO? Świetne pytanie - istnieje bardzo dużo powodów, żeby to zrobić. Najprostszy jaki mi przychodzi do głowy - żeby program mógł sam używać przeglądarki napisanej z myślą o ludziach, a więc poprawnie sformułować w języku naturalnym swój problem.

Opisujemy obiekty poprzez cechy (trait/interface/type class). Jeśli typ implementuje cechę, można go użyć w danym miejscu. Krótka piłka.

Masz rację - ale nie do końca. Współczesne języki są tak napisane, że wartości zmiennych zawsze istnieją (jako wartość nieznaną czyli taki hack wymyślono NULL/nullptr). Program napisany w takim języku nie będzie potrafił zdefiniować sobie kodu, który ma szansę rozwiązać jakiś matematyczny problem i nie będzie w związku z tym w stanie sformułować pytania o taki kod. A mnie się marzy programowanie w języku, który umożliwia sformułowanie pytania o istnienie takiego kodu, To nawet nie jest żadna Sztuczna Inteligencja, to domknięcie dziury, jaka jest w OOP. Po prostu chcę mieć język, który jest bliżej matematyki niż to, co mamy. Jeszcze bliżej niż FP. Który wie, że na przykład tego a tego nie da się rozwiązać analitycznie, ale można spróbować numerycznie. Albo wie, że czegoś nie da się skonstruować z natury rzeczy.

Co do dowodzenia, to ile wiem, Idris zapewnia dość rozbudowane możliwości formalnego udowadniania twierdzeń na temat kodu. Tutaj to już w ogóle przydają się typy z parametrem (wartość, nie inny typ; np. rozmiar kolekcji).

Ja w Chomiku w ogóle nie mam typów oprócz wbudowanych. Cały ten szał z tworzeniem włąsnych typów jest mi obojętny, chociaż bardzo lubię C++.

3
Paweł Biernacki napisał(a):

Masz rację - ale nie do końca. Współczesne języki są tak napisane, że wartości zmiennych zawsze istnieją (jako wartość nieznaną czyli taki hack wymyślono NULL/nullptr).

Oczywiście, że nie.


f x = f x

undef::Int
undef = f 1

Gwoli ścisłości - czy wartość undef istnieje to można się kłócić. Można na tym wykonywać jakieś działania, przekazywać do funkcji - tylko nie można obliczyć.

2
Paweł Biernacki napisał(a):

Tak, tak właśnie jest, z pojawieniem się closures i lambd to stało się możliwe. Ale closures czy lambdy to raczej wyjątek od reguły, a u mnie reguła. Może to nie jest bardzo innowacyjne, ale jest lepsze niż ten święty podział na dane i kod, który jest nawet w OOP, pod nazwą enkapsulacji.

Tak się robi, np. w Haskellu. Pracuj tak dalej, a pewnie niedługo wynajdziesz monady. :D

PO CO? Świetne pytanie - istnieje bardzo dużo powodów, żeby to zrobić. Najprostszy jaki mi przychodzi do głowy - żeby program mógł sam używać przeglądarki napisanej z myślą o ludziach, a więc poprawnie sformułować w języku naturalnym swój problem.

Skoro chodzi o język interfejsu użytkownika to może jednak prolog? Mozna w nim zrobić frontend do czegoś napisanego w innym języku. Tak czy inaczej w pewnym momencie będziesz musiał przyjąć bardziej ścisły zapis, strawny dla komputera. I teraz pytanie, skoro można podzielić się na 2 warstwy i każdą napisać w języku do tego najlepiej nadającym się, to po co wynajdywać jeden język, w którym napiszesz obie i dowiesz się, że mamy różne języki do różnych zadań, bo każde zadanie to inne priorytety. :)

Masz rację - ale nie do końca. Współczesne języki są tak napisane, że wartości zmiennych zawsze istnieją (jako wartość nieznaną czyli taki hack wymyślono NULL/nullptr). Program napisany w takim języku nie będzie potrafił zdefiniować sobie kodu, który ma szansę rozwiązać jakiś matematyczny problem i nie będzie w związku z tym w stanie sformułować pytania o taki kod. A mnie się marzy programowanie w języku, który umożliwia sformułowanie pytania o istnienie takiego kodu,

Czyli pytanie o idealny język do robienia prototypu, gdzie nie wiemy do końca jaki jest problem. Lisp jest językiem do takich rzeczy, choć prolog też mógłby być na miejscu. Co się tyczy NULLi, to kolejny zabytek. W nowoczesnych językach używa się Option<T>, żeby język mógł wymuszać poprawne rozpatrywanie sytuacji wyjątkowych (lub przynajmniej utrudnić obejście tego)

Co do dowodzenia, to ile wiem, Idris zapewnia dość rozbudowane możliwości formalnego udowadniania twierdzeń na temat kodu. Tutaj to już w ogóle przydają się typy z parametrem (wartość, nie inny typ; np. rozmiar kolekcji).

Ja w Chomiku w ogóle nie mam typów oprócz wbudowanych. Cały ten szał z tworzeniem włąsnych typów jest mi obojętny, chociaż bardzo lubię C++.

Nie rozumiem, chcesz gwarancji na temat kodu, a odrzucasz najbardziej podstawowe narzędzie do tego? Chyba nigdy za bardzo nie pokochałeś statycznego typowania w stylu Haskella czy Rusta?

0
jarekr000000 napisał(a):
Paweł Biernacki napisał(a):

Masz rację - ale nie do końca. Współczesne języki są tak napisane, że wartości zmiennych zawsze istnieją (jako wartość nieznaną czyli taki hack wymyślono NULL/nullptr).

Oczywiście, że nie.


f x = f x

undef::Int
undef = f 1

Gwoli ścisłości - czy wartość undef istnieje to można się kłócić. Można na tym wykonywać jakieś działania, przekazywać do funkcji - tylko nie można obliczyć.

No racja, zapomniałem o Haskellu. Ale i w C++ jest teraz std::optional. Tylko, że mam na celu stworzenie czegoś bardziej holistycznego, czy X istnieje, czy X da się skonstruować, czy kod tworzący X istnieje, czy może istnieć itd. Można argumentować, że piszę program w Chomiku, a więc w sumie w C++, ale Chomik to jest jednak bardzo użyteczna warstwa abstrakcji.

0
elwis napisał(a):

Typy Person, Place i Action pewnie musiałyby już być jakimiś kolekcjami, żeby dało się je dodawać w czasie wykonywania…

newtype Person = Person String

Coś takiego nie zadziała? Chyba, że nie zrozumiałem o czym mowa.

0
elwis napisał(a):
Paweł Biernacki napisał(a):

Tak, tak właśnie jest, z pojawieniem się closures i lambd to stało się możliwe. Ale closures czy lambdy to raczej wyjątek od reguły, a u mnie reguła. Może to nie jest bardzo innowacyjne, ale jest lepsze niż ten święty podział na dane i kod, który jest nawet w OOP, pod nazwą enkapsulacji.

Tak się robi, np. w Haskellu. Pracuj tak dalej, a pewnie niedługo wynajdziesz monady. :D

;))))))

PO CO? Świetne pytanie - istnieje bardzo dużo powodów, żeby to zrobić. Najprostszy jaki mi przychodzi do głowy - żeby program mógł sam używać przeglądarki napisanej z myślą o ludziach, a więc poprawnie sformułować w języku naturalnym swój problem.

Skoro chodzi o język interfejsu użytkownika to może jednak prolog?

Nie, Prolog jest zbyt słaby. Gdybym potrzebował jakiegoś dowodzenia (takiego jak w Prologu) to pewnie bym podczepił Prolog pod program w C++, kiedyś to już robiłem.

Mozna w nim zrobić frontend do czegoś napisanego w innym języku. Tak czy inaczej w pewnym momencie będziesz musiał przyjąć bardziej ścisły zapis, strawny dla komputera. I teraz pytanie, skoro można podzielić się na 2 warstwy i każdą napisać w języku do tego najlepiej nadającym się, to po co wynajdywać jeden język, w którym napiszesz obie i dowiesz się, że mamy różne języki do różnych zadań, bo każde zadanie to inne priorytety. :)

I w Chomiku i w Esc mam do czynienia z językami formalnymi, a więc ze ścisłym zapisem. Nie mam problemu z używaniem języków formalnych, mam problem z OOP, które jest konceptualnie zbyt słabe do modelowania wielu kwestii matematycznych. Już mówiłęm jakich - tożsamość, równość, istnienie, konstruowalność, praktyczna konstruowalność.

I ja wiem dlaczego tak jest. Mści się to, że nadajecie w tych wszystkich językach jednoczłonowe nazwy zmiennym/funkcjom. Nazwy skłądające się z jednego identyfikatora. W Chomiku nazwy są wieloczłonowe link. Dzięki temu nie ma innej składni dla elementów tablicy, dla pól rekordu, nie ma tych wszystkich [], ., ->, * itp. Program w Chomiku potrafi skonstruować nową nazwę, nawet taką, której nie przewidział programista, w ogóle każda wartość każdego typu może być użyta jako człon nazwy zmiennej. Po drugie jeszcze z czasów Fortranu jest założenie, że to czy mamy na myśli zmienną czy jej wartość wynika z kontekstu:

X=10; /* tu mamy przypisanie ZMIENNEJ X */
Y=X;  /* tu mamy ewaluację WARTOŚCI X */

I tak twórcy języków kopiują to rozwiązanie jeden od drugiego, żaden nie pomyśli po co to założenie. U mnie żeby ewaluować zmienną trzeba zamknąć jej nazwę w nawiasach trójkątnych. To zresztą nie chodzi o składnię, mogłoby być równie dobrze EVAL_BEGIN i EVAL_END. To założenie to też był konstrukcyjny błąd, z mojego, tj. chomikowego punktu widzenia. Dzięki temu, że mam wieloczłonowe nazwy zmiennych udało mi się wyeliminować instrukcję warunkową, link.

Masz rację - ale nie do końca. Współczesne języki są tak napisane, że wartości zmiennych zawsze istnieją (jako wartość nieznaną czyli taki hack wymyślono NULL/nullptr). Program napisany w takim języku nie będzie potrafił zdefiniować sobie kodu, który ma szansę rozwiązać jakiś matematyczny problem i nie będzie w związku z tym w stanie sformułować pytania o taki kod. A mnie się marzy programowanie w języku, który umożliwia sformułowanie pytania o istnienie takiego kodu,

Czyli pytanie o idealny język do robienia prototypu, gdzie nie wiemy do końca jaki jest problem. Lisp jest językiem do takich rzeczy, choć prolog też mógłby być na miejscu. Co się tyczy NULLi, to kolejny zabytek. W nowoczesnych językach używa się Option<T>, żeby język mógł wymuszać poprawne rozpatrywanie sytuacji wyjątkowych (lub przynajmniej utrudnić obejście tego)

Prawda. To tylko tak odnośnie hacków.

Co do dowodzenia, to ile wiem, Idris zapewnia dość rozbudowane możliwości formalnego udowadniania twierdzeń na temat kodu. Tutaj to już w ogóle przydają się typy z parametrem (wartość, nie inny typ; np. rozmiar kolekcji).

Ja w Chomiku w ogóle nie mam typów oprócz wbudowanych. Cały ten szał z tworzeniem włąsnych typów jest mi obojętny, chociaż bardzo lubię C++.

Nie rozumiem, chcesz gwarancji na temat kodu, a odrzucasz najbardziej podstawowe narzędzie do tego? Chyba nigdy za bardzo nie pokochałeś statycznego typowania w stylu Haskella czy Rusta?

Tak włąśnie jest. Całkowicie odrzuciłem tworzenie własnych typów, nie jest mi to potrzebne. A tam, gdzie język tworzy bardziej złożone obiekty tam odwołuję się do nich za pomocą ich indeksu (np. standardowe wyjście to strumień o indeksie 0). Jest taki dialekt Chomika, nazywa się SDL_Chomik (od biblioteki SDL2). Po utworzeniu nowego obrazka albo wczytaniu fontu ten SDL_Chomik ustawia pewną zmienną na wartość indeksu ostatnio utworzonego obrazka/fontu. I żeby wyświetlić ten obrazek używam potem tej wartości indeksu z odpowiednim kodem.

1
Paweł Biernacki napisał(a):

Mam nadzieję na zrobienie czegoś lepszego niż programowanie obiektowe, potrzebne mi jest tylko jako punkt odniesienia. To istotnie jest inny paradygmat, trochę bliższy matematyki, moim zdaniem. Na przykłąd w OOP są trudności z pojęciem tożsamości i równości obiektów (czy dwie różne instancje o tych samych wartościach atrybutów to ten sam obiekt czy dwa różne).

Jeśli potrzebujemy zrobić z obiektu "value object" zamiast "entity" (idąc w terminologię DDD) i chcemy porównywać obiekty pod kątem tego, jakie mają atrybuty, to w językach OOP zwykle jest jakiś sposób porównania. Można wywołać funkcję, która porównuje obiekty (niezależnie od tego, czy taka funkcja jest w języku, bo jakby nie było, to można taką napisać). W językach, które mają przeciążanie operatorów, moglibyśmy nadpisać operator == albo zastosować inny sposób, właściwy dla danego języka.

Czyli nie powiedziałbym, żeby w OOP były trudności z pojęciem tożsamości i równości obiektów.

Paweł Biernacki napisał(a):

(...) Uczyłem się Haskella, ale nie nauczyłem się go.

I dlatego Haskell nie został mainstreamowym językiem programowania :D Bo to za trudne.

3
LukeJL napisał(a):

Czyli nie powiedziałbym, żeby w OOP były trudności z pojęciem tożsamości i równości obiektów.

Bo po prawdzie to pojęcie tożsamości i równości obiektów to problem fundamentalny (i trudny) przy definiowaniu matematyki (formalizmów).
https://en.wikipedia.org/wiki/Homotopy_type_theory (<- Warto popatrzeć na daty publikacji)

0
LukeJL napisał(a):

Jeśli potrzebujemy zrobić z obiektu "value object" zamiast "entity" (idąc w terminologię DDD) i chcemy porównywać obiekty pod kątem tego, jakie mają atrybuty, to w językach OOP zwykle jest jakiś sposób porównania. Można wywołać funkcję, która porównuje obiekty (niezależnie od tego, czy taka funkcja jest w języku, bo jakby nie było, to można taką napisać). W językach, które mają przeciążanie operatorów, moglibyśmy nadpisać operator == albo zastosować inny sposób, właściwy dla danego języka.

Czyli nie powiedziałbym, żeby w OOP były trudności z pojęciem tożsamości i równości obiektów.

Trudność z tożsamością pojawia się np. jeśli obiekty różnych klas są sobie równe. Np. suma dwóch liczb jest jednocześnie iloczynem dwóch innych liczb. Obiekt powinien być jak enum - mieć tylko tożsamość. Pojęcie klasy zostało wprowadzone do OOP nieco nieporządnie - klasa to abstrakcyjny byt, bardziej funkcja niż zbiór. Jako taki zawsze istnieje (nie ma sensu pytać o istnienie klasy, ani czy klasa jest dobrze zdefiniowana). Co innego obiekt. Może być ściśle zdefiniowany, ale nie istnieć. W algebrze dowodzi się np. że elementy neutralne dodawania i mnożenia istnieją i że wszystkie są sobie równe, pierwszy nazywany jest zerem, drugi jedynką.

Obiekty mogą być formalnie różne (być obiektami różnych klas), ale możemy nie wiedzieć czy są tożsame. Możemy nawet czasem mieć dowód, że nie uda się nam odpowiedzi na to pytanie znaleźć. Wzięliśmy od matematyków ich notację, ale trochę bez zastanowienia, tak że OOP po prostu nie umie wyrazić pewnych problemów. Nic nie szkodzi, napisany w Chomiku Esc będzie umiał ;))))

Paweł Biernacki napisał(a):

(...) Uczyłem się Haskella, ale nie nauczyłem się go.

I dlatego Haskell nie został mainstreamowym językiem programowania :D Bo to za trudne.

No, nie było tak źle. Trochę popisałem, ale przestałem. Nie porwał mnie jakoś.

1
Paweł Biernacki napisał(a):

Mój pomysł polega na tym, że klasy istnieją, owszem, ale tylko tak jak enumy, to znaczy mają tożsamość.

Gdyby ktoś powiedział mi że "coś istnieje jako enum, to znaczy ma tożsamość" to powiedziałbym że to jest po prostu instancja czegoś (instancja obiektu, prymityw albo kolekcja).

Paweł Biernacki napisał(a):

To samo obiekty, liczby rzeczywiste, liczby całkowite itd. Na początek tworzymy obiekty: ABC (trójkąt), odcinki AB, BC, CA, oraz liczby rzeczywiste "real zero", "real one", "length of AB", "length of BC", "length of CA". Obiekty, liczby rzeczywiste, całkowite, boolowskie, teksty i kody są opisane faktami. Fakty nie są obiektami!

To mi brzmi jakbyś chciał modelować domenę, bez specjalnego zachowania. Ale zobaczymy co z tego wyjdzie.

Paweł Biernacki napisał(a):

Czyli klasy działają trochę jak konstruktory w OOP.

Według niektórych definicji to w OOP klasy właśnie są konstruktorami (tzn. nie do końca, klasa to jest "konstruktor+destruktor", ale w językach w których jest garbage collector, to mało kto używa destruktorów, to można powiedzieć że klasa jest tożsama z konstruktorem, tzn. klasa definiuje wartości i typy, tak samo jak konstruktor).

Także tutaj nic odkrywczego i sprzecznego z OOP nie wymyśliłeś.

Paweł Biernacki napisał(a):

Różni się to od OOP tym, że obiekty nie są utożsamiane z krotkami atrybutów, tylko każdy obiekt ma po prostu tożsamość, podobnie jak liczba rzeczywista czy inna, albo tekst.

Nie różni się to chyba specjalnie od OOP, bo w Javie mogę zrobić new Object() i on też nie będzie miał żadnego atrybutu, a tylko i wyłącznie tożsamość.

Paweł Biernacki napisał(a):

Poza tym obiekty mogą istnieć i być konstruowalne, ale nie realistycznie konstruowalne (tak jak np. rozwinięcie dziesiętne liczby PI). Albo istnieć i nie być konstruowalne. Albo mieć nazwę i definicję, ale nie istnieć (jak np. liczba X mniejsza od 0 i jednocześnie większa od 5). W sumie programista może w tym systemie zbliżyć się bardziej do matematyki niż w tradycyjnym OOP.

A to mi z kolei brzmi jak "logical syllogism". Czyli używasz określenia "istnieć" w dwóch znaczeniach. W jednym znaczeniu mówisz że obiekt jest zaalokowany w pamięci ("istnieje"), a w drugi mówisz że spełnia albo nie spełnia jakichś kryteriów ("istnieje").

Ja bym na Twoim miejscu używał odręnych słów żeby nie wpaść w pułapkę.

Paweł Biernacki napisał(a):

Mam nadzieję doprowadzić go do stanu, w którym zauważy, że dwa obiekty zdefiniowane automatycznie (tj. nie w domain_knowledge.chomik) są sobie równe i wyprowadzić metodę konstrukcji "length of CA".

No spoko pomysł, tylko nie za bardzo wiem do czego miałbyś tego użyć? Dopóki nie ma jakiegoś konkretnego use case'u dla tego to dla mnie to jest raczej mało interesujące.

0
Riddle napisał(a):
Paweł Biernacki napisał(a):

Mój pomysł polega na tym, że klasy istnieją, owszem, ale tylko tak jak enumy, to znaczy mają tożsamość.

Gdyby ktoś powiedział mi że "coś istnieje jako enum, to znaczy ma tożsamość" to powiedziałbym że to jest po prostu instancja czegoś (instancja obiektu, prymityw albo kolekcja).

Dla mnie obiekt to tak jak pojęcie. Definiują go tylko fakty na jego temat. Jest kwestią dowodu, czy odpowiadający temu pojęciu byt istnieje rzeczywiście. A jeśli istnieje - to czy da się skonstruować.

Paweł Biernacki napisał(a):

To samo obiekty, liczby rzeczywiste, liczby całkowite itd. Na początek tworzymy obiekty: ABC (trójkąt), odcinki AB, BC, CA, oraz liczby rzeczywiste "real zero", "real one", "length of AB", "length of BC", "length of CA". Obiekty, liczby rzeczywiste, całkowite, boolowskie, teksty i kody są opisane faktami. Fakty nie są obiektami!

To mi brzmi jakbyś chciał modelować domenę, bez specjalnego zachowania. Ale zobaczymy co z tego wyjdzie.

Zobaczymy, postaram się. Myślę, że uda się uchwycić i zmienne, więc dynamicznie zmieniający się świat. Nie chciałbym wpaść w pułapkę taką jak Prolog, który ma kłopot z pojęciem zmiennej (no, można retraktować fakty z bazy).

Paweł Biernacki napisał(a):

Czyli klasy działają trochę jak konstruktory w OOP.

Według niektórych definicji to w OOP klasy właśnie są konstruktorami (tzn. nie do końca, klasa to jest "konstruktor+destruktor", ale w językach w których jest garbage collector, to mało kto używa destruktorów, to można powiedzieć że klasa jest tożsama z konstruktorem, tzn. klasa definiuje wartości i typy, tak samo jak konstruktor).

Także tutaj nic odkrywczego i sprzecznego z OOP nie wymyśliłeś.

Tak - sprzeczność z OOP widzę gdzie indziej. Najogólniej mówiąc uważam za błąd utożsamianie obiektu z rekordem atrybutów, utożsamianie instancjacji z faktem istnienia obiektu, milczące założenie że dwa obiekty różnych klas muszą być różne itp. Może ja to zaimplementuję do końca i Wam pokażę.

Paweł Biernacki napisał(a):

Różni się to od OOP tym, że obiekty nie są utożsamiane z krotkami atrybutów, tylko każdy obiekt ma po prostu tożsamość, podobnie jak liczba rzeczywista czy inna, albo tekst.

Nie różni się to chyba specjalnie od OOP, bo w Javie mogę zrobić new Object() i on też nie będzie miał żadnego atrybutu, a tylko i wyłącznie tożsamość.

Tak, taki obiekt jest chyba najbliżej tego, co mam na myśli. Jeszcze bliżej jest enum, czyli coś co można porównać z innym enumem. Jeśli wyjdzie, że to ten sam enum, to znaczy, że chodzi o ten sam obiekt. Ale jeśli nie jest ten sam, to MOŻE chodzić o dwa różne obiekty, ale nie musi. Może się np. okazać, że dwie liczby zdefiniowane w różny sposób są sobie równe (aa+bb jest równe c*c). I możemy to wiedzieć nawet nie znając wartości żadnej z liczb a,b,c.

Paweł Biernacki napisał(a):

Poza tym obiekty mogą istnieć i być konstruowalne, ale nie realistycznie konstruowalne (tak jak np. rozwinięcie dziesiętne liczby PI). Albo istnieć i nie być konstruowalne. Albo mieć nazwę i definicję, ale nie istnieć (jak np. liczba X mniejsza od 0 i jednocześnie większa od 5). W sumie programista może w tym systemie zbliżyć się bardziej do matematyki niż w tradycyjnym OOP.

A to mi z kolei brzmi jak "logical syllogism". Czyli używasz określenia "istnieć" w dwóch znaczeniach. W jednym znaczeniu mówisz że obiekt jest zaalokowany w pamięci ("istnieje"), a w drugi mówisz że spełnia albo nie spełnia jakichś kryteriów ("istnieje").

Tu akurat ustrzegłem się tego błędu (dwóch znaczeń słowa "istnieje"). Rozwinięcie dziesiętne liczby PI jest dobrze zdefiniowane i istnieje (w sensie dokładnie jedno rozwinięcie, dokładnie jedna liczba spełnia tą definicję), i wiadomo jak obliczać liczbę PI, czyli teoretycznie można ją skonstruować, ale nie jest realistycznie konstruowalne, bo rozwinięcie to jest nieskończone.

Ja bym na Twoim miejscu używał odręnych słów żeby nie wpaść w pułapkę.

Paweł Biernacki napisał(a):

Mam nadzieję doprowadzić go do stanu, w którym zauważy, że dwa obiekty zdefiniowane automatycznie (tj. nie w domain_knowledge.chomik) są sobie równe i wyprowadzić metodę konstrukcji "length of CA".

No spoko pomysł, tylko nie za bardzo wiem do czego miałbyś tego użyć? Dopóki nie ma jakiegoś konkretnego use case'u dla tego to dla mnie to jest raczej mało interesujące.

Dla mnie to niezmiernie interesujące. Już sama perspektywa poprawienia OOP tak, żeby stało się bliższe matematyki jest bardzo ciekawa. A po drugie wyobraź sobie program, który potrafi opisać, a może nawet skonstruować pewną rodzinę programów. Twórcy OOP chcieli dobrze, ale niepotrzebnie założyli, że kwestie istnienia i konstruowalności obiektów muszą pozostać w głowach programistów. Ja bym chciał jak najwięcej informacji przekazać komputerowi. No i spodziewam się, że ta wiedza, całkowicie formalna, przyniesie zysk w postaci silniejszych, tańszych programów. Z reużywalną biblioteką standardową napisaną w czymś takim jak Chomik.

2

Tak - sprzeczność z OOP widzę gdzie indziej. Najogólniej mówiąc uważam za błąd utożsamianie obiektu z rekordem atrybutów, utożsamianie instancjacji z faktem istnienia obiektu,

W podejściu DDD encje (koncepcyjne obiekty mające tożsamość) mogą istnieć nawet zanim zostaną utworzone w programie (a ich stan jest zapisywany w bazie danych i później dopiero odtwarzany w programie).

Dlatego w DDD mówi się o tym, że utworzenie instancji obiektu w programie to takie "reconstitution" (przynajmniej Eric Evans używa takiego słowa w swojej książce), bo te obiekty już istnieją, tylko trzeba je po prostu przywrócić przez utworzenie instancji.

0

Zauważyłem taką ciekawostkę i spieszę się nią podzielić z Wami. Otóż oprócz faktów opisujących np. "X exists" mam jeszcze zmienne boolowskie "X is known to exist" i "X is known not to exist". To samo z "is constructable", "is realistically constructable", "is constructed". Może być tak, że obiekt istnieje, ale my jeszcze o tym nie wiemy. A jak już wiemy, to zmienna "X is known to exist" staje się równa true. Te zmienne "X is known to exist" i "X is known not to exist" nie mogą być jednocześnie true, ale mogą być obie false. I to nawet w sytuacji, gdy X w rzeczywistości istnieje.

Druga ciekawostka - w nowej wersji nie będzie już klas "triangle" i "right triangle". Zdecydowałem, że wprowadzę pojęcie zbioru, a klasy to będą wyłącznie konstruktory. Zbiory, tak jak klasy, zawsze istnieją (jako abstrakcyjne byty), tylko że niektóre z nich są puste a inne są nawet nieskończone. Nie będę miał problemu ze słynną antynomią "zbiór wszystkich zbiorów".

Może być, że oprócz konstruowalności realistycznej wprowadzę jeszcze dwa jej rodzaje - konstruowalność analityczną i numeryczną. Mam wielką ochotę.

Na moim VPSie jest strona dla Esc: https://www.perkun.org/esc.html.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.