Czy F# jest językiem funkcyjnym czy obiektowo-funkcyjnym?

Czy F# jest językiem funkcyjnym czy obiektowo-funkcyjnym?
F# jest funkcyjny, nie jest obiektowy
0%
0% [0]
F# jest obiektowo-funkcyjny
86%
86% [6]
Funkcyjność w F# ssie i to zakamuflowany język obiektowy :p
14%
14% [1]
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:5 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
1

Czy to że List w F# implementuje interfejsy jest wystarczającym dowodem na to żeby uzznać że F# jest językiem obiektowym?
Takie pytanie się narodziło w mojej głowie

Początek deklaracji typu List

Kopiuj
type List<'T> = 
       | ([])  :                  'T list
       | ( :: )  : Head: 'T * Tail: 'T list -> 'T list
       interface System.Collections.Generic.IEnumerable<'T>
       interface System.Collections.IEnumerable
       interface System.Collections.Generic.IReadOnlyCollection<'T>
       interface System.Collections.Generic.IReadOnlyList<'T>

źródło
Dokumentacja


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
edytowany 1x, ostatnio: KamilAdam
SA
Było ankietę założyć, vox populi, vox dei.
KamilAdam
Taka może być? czy coś zmienić?
SA
Nie kompiluje się, bo nie przechodzi exhaustiveness check, brakuje "obiektowy'.
SA
Dokładnie tej opcji brakowało.
hauleth
A czym to się różni od derive w Haskellu?
KamilAdam
Chyba deriving? deriving automagicznie tworzy implementację (instancję) dla TypeClass
hauleth
Tak, o to chodziło, dawno Haskella nie tykałem. No ok, ale technicznie jaka to różnica z punktu widzenia programisty?
KamilAdam
ale technicznie jaka to różnica z punktu widzenia programisty? Między czym a czym?
Wibowit
interface jest wbudowany w typ (więc musisz go wbudować w miejscu definicji klasy), a instancja typeclassy jest zdefiniowana obok (możesz ją zdefiniować w co najmniej dwóch miejscach: obok deklaracji type classy albo obok definicji typu, któremu dostarczasz instancję typeclassy). różnica jest (teoretycznie) znacząca. dla przykładu jeśli mam w bibliotece klasę, która nie implementuje mojego interfejsu to z tym nic nie zrobię, ale jeśli chcę zaimplementować swoją typeclassę dla typu z biblioteki, którą nie kontroluję, to mogę to zrobić. pewnie trochę zamotałem :)
Wibowit
inaczej mówiąc: typeclassy rozwiązują https://en.wikipedia.org/wiki/Expression_problem ale interfejsy nie
bakunet
  • Rejestracja:prawie 8 lat
  • Ostatnio:około godziny
  • Lokalizacja:Polska
  • Postów:1596
1

Wg. mojej najlepszej wiedzy jest najczęściej wykorzystywany jako funkcyjny, choć obiektowo pisać też się da. Pierwszy znaleziony wynik:
https://fsharpforfunandprofit.com/posts/object-oriented-intro/

.andy
  • Rejestracja:ponad 16 lat
  • Ostatnio:około 3 lata
  • Postów:1524
1

Nie trzeba ankiety ;)

https://pl.wikipedia.org/wiki/Programowanie_wieloparadygmatowe

F# – wieloparadygmatowy język programowania zawierający w sobie głównie cechy języka funkcyjnego, ale umożliwiającym także pisanie kodu imperatywnego oraz obiektowego.


Software is like sex: it's better when it's free.
- Linus Torvalds
edytowany 1x, ostatnio: .andy
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 14 godzin
  • Lokalizacja:Wrocław
0

Jest spora różnica między fuknkcyjno-obiektowy, a trzeba używać obiektów.
Jest wiele języków imperatywnych, w których np. wcale nie trzeba używać pętli.

S9
  • Rejestracja:ponad 4 lata
  • Ostatnio:około 2 lata
  • Lokalizacja:Warszawa
  • Postów:1092
3

Tak btw - są w F# algebraiczne struktury danych jak w Haskellu czy nawet już Javie?


edytowany 1x, ostatnio: scibi_92
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:5 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
1
somekind napisał(a):

Jest spora różnica między fuknkcyjno-obiektowy, a trzeba używać obiektów.

To proste pytanie. Klasyczny przykład polimorfizmu w OO:

Kopiuj
[<AbstractClass>]
type XmasCharacter() =
    abstract member Speak: unit -> unit

type SantaClaus() =
    inherit XmasCharacter()
    override this.Speak() = printfn "Ho Ho Ho!"
    
type DedMoroz() =
    inherit XmasCharacter()
    override this.Speak() = printfn "Xo Xo Xo!"

// create Santa, then cast the reference to XmasCharacter type
let grandpa = SantaClaus() :> XmasCharacter 
grandpa.Speak() // prints Ho Ho Ho!

Jak zrobić to w F# bez obiektów skoro nie trzeba używać obiektów?


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
S9
A jak to bys mógł napisać w Scali bez polimorfizmu obiektowego?
KamilAdam
Będzie ciężko bo Scala 2 nie ma prawdziwych TypeClass tylko rzeźbione na ... obiektach :D A Scali 3 jeszcze nieznam :( Mogę w Haskellu :p
Wibowit
scala kompiluje się do javowego bajtkodu, więc pod spodem są tak czy siak klasy, bo nic innego być nie może. jednak jedną z cech charakterystycznych typeclass jest oddzielenie stanu od zachowania oraz automatyczne (implicit) wybieranie instancji typeclassy przez kompilator (scala ma implicity). to co podał @KamilAdam w poście to nie wygląda jak obiekt, bo ma tylko zachowanie, a nie ma w ogóle stanu. trochę słaby przykład? czy może tak miało być?
KamilAdam
@Wibowit: wyobraź sobie że jest strasznie mało materiałów w internecie o F# :P poszukam czegoś lepszego :D
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:5 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
0

Dobra, za radą @Wibowit dodałem stan:

Kopiuj
[<AbstractClass>]
type XmasCharacter() =
    abstract member Speak: unit -> unit

type SantaClaus(x: int) =
    inherit XmasCharacter()
    override this.Speak() = printfn "Ho Ho Ho %i!" x 

type DedMoroz(x: string) =
    inherit XmasCharacter()
    override this.Speak() = printfn "Xo Xo Xo %s!" x

// create Santa, then cast the reference to XmasCharacter type
let grandpa = SantaClaus(666) :> XmasCharacter 
grandpa.Speak() // prints Ho Ho Ho 666!

@somekind Jak zrobić to bez obiektów/klas w F# ?

Wersja z ToString :P

Kopiuj
[<AbstractClass>]
type XmasCharacter() =
    abstract member Speak: unit -> unit

type SantaClaus(x: int) =
    inherit XmasCharacter()
    override this.Speak() =
        let s = "Ho Ho Ho " + x.ToString()
        printfn "%s" s

type DedMoroz(x: string) =
    inherit XmasCharacter()
    override this.Speak() =
        let s = "Xo Xo Xo " + x.ToString()
        printfn "%s" s

// create Santa, then cast the reference to XmasCharacter type
let grandpa = SantaClaus(666) :> XmasCharacter 
grandpa.Speak() // prints Ho Ho Ho 666

Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
edytowany 3x, ostatnio: KamilAdam
Zobacz pozostałe 2 komentarze
Wibowit
@stivens: niekoniecznie musi być mutowalny, wystarczy taki podawany z konstruktora. niemutowalny obiekt to chyba nie herezja, no nie?
stivens
@Wibowit: ale to wtedy lista z Haskella tez jest obiektem? Myslalem ze chodzi o taki w rozumieniu OOP
stivens
1 :: 2 :: 3 :: [] - obiekt?
Wibowit
lista z Haskella tez jest obiektem? - raczej nie, bo nie ma metod (tzn. funkcji dostępnych poprzez uchwyt do listy). są funkcje leżące w tej samej przestrzeni nazw co typ listy, ale to nie znaczy, że są połączone w obiekt. jak zrobię funkcje operujące na tablicy to ta nie stanie się nagle obiektem.
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:5 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
0

@stivens: Specjalnie dla ciebie - mutowalny stan:

Kopiuj
[<AbstractClass>]
type XmasCharacter() =
    abstract member Speak: unit -> unit

type SantaClaus(x: int) =
    inherit XmasCharacter()
    let mutable x = x
    member this.SetX value =
        x <- value
    override this.Speak() =
        let s = "Ho Ho Ho " + x.ToString()
        printfn "%s" s

type DedMoroz(x: string) =
    inherit XmasCharacter()
    let mutable x = x
    member this.SetX value =
        x <- value
    override this.Speak() =
        let s = "Xo Xo Xo " + x.ToString()
        printfn "%s" s

// create Santa, then cast the reference to XmasCharacter type

let santa = SantaClaus(666)

let grandpa = santa:> XmasCharacter 
grandpa.Speak() // prints Ho Ho Ho 666

santa.SetX(777) 

grandpa.Speak() // prints Ho Ho Ho 777

Jeszcze chwila i zacznę wysyłać CV na programistę F#


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
Zobacz pozostałe 11 komentarzy
KamilAdam
Hm, Jak jest dobra biblioteka z map/flatMap/fold to nawet w Javie rzadko trzeba robić mutowalny stan. Dlatego myślę że to czy stan jest mutowalny czy niemutowalny nie powinno wyznaczać czy język jest obiektowy czy nie (ale mogę się mylić)
stivens
No to mowie, ze jest niepoprawna :P ale post powyzej jest pod takie zalozenie
stivens
A dla mnie ma o tyle lekkie znaczenia, ze show x i x.show() sa wzglednie podobne a void x.setFoo(bar) i newX = withNewFoo x bar to juz zupelnie inna bajka
stivens
No i czesto tez mozna uslyszec, ze obiekty w OOP to "sa podobne do realnych obiektow, gdzie jak cos z nimi robisz to sie zmienia ich stan. Np. jak ugryziesz jablko to zaczyna wygladac jak logo Apple, zmienilo sie". Swoja droga imho to jednak bardziej monada stanu niz mutacja. No bo jak zrobisz zdjecie takiemu jablku przed ugryzieniem a potem go ugryziesz to ono na zdjeciu sie nie zmieni nijak. A w imperatywnym swieci jablko na zdjeciu rowniez by sie zmienilo (* chyba ze deffensive programming i agresywna kopia, ale chodzi o wiele referencji), przeciez to ten sam obiekt :)
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:5 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
1

@scibi_92: Przykład Polimorfizmu w Haskellu na TypeClassach, z oczywistych powodów pominę mutowalny stan :P

Kopiuj
main = putStrLn (speak grandpa)
  where grandpa = SantaClaus 666

--  tu definiujemy typy
newtype SantaClaus = SantaClaus { unSantaClaus :: Int }
newtype DedMoroz = DedMoroz { unDedMoroz :: String }

-- tu definiujemy "interfejs"
class XmasCharacter a where
  -- sygnatura metody
  speak :: a -> String

-- tu definiujemy implementacje
instance XmasCharacter SantaClaus where
  -- ciało metody
  speak a = "Ho Ho Ho " ++ show (unSantaClaus a) -- znów mamy `show` czyli Haskellowy odpowiednik `toString`

instance XmasCharacter DedMoroz where
  -- ciało metody
  speak a = "Xo Xo Xo " ++ unDedMoroz a

Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
edytowany 1x, ostatnio: KamilAdam
S9
  • Rejestracja:ponad 4 lata
  • Ostatnio:około 2 lata
  • Lokalizacja:Warszawa
  • Postów:1092
2

Dobra, znalazłem przykład ze Scali


somekind
Miła odmiana od forum, gdy tak się posłucha jak ktoś konkretnie i merytorycznie opowiada na temat Scali.
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 14 godzin
  • Lokalizacja:Wrocław
0
KamilAdam napisał(a):

To proste pytanie. Klasyczny przykład polimorfizmu w OO:

W moim mniemaniu proste pytanie zadałem ja, w komentarzach do wiadomego wątku. Odpowiedzi nie otrzymałem.

Jak zrobić to w F# bez obiektów skoro nie trzeba używać obiektów?

Nie bardzo rozumiem, co próbujesz udowodnić ani czemu mnie o to pytasz. Masz problem z rozumieniem czasowników modalnych?
Piszesz sobie obiektowy kod w języku, który to umożliwia, bo chcesz i możesz. Z tego nie wynika, że w ogólności cokolwiek trzeba, a jedynie tyle, że dobrałeś taki przykład.

SL
  • Rejestracja:około 7 lat
  • Ostatnio:13 minut
  • Postów:862
1

Jest obiektowy praktycznie tak jak każdy inny współczesny język. OOP jest tak pustym sloganem, bo w zasadzie ciężko powiedzieć czym programowanie obiektowe jest. Dla mnie OOP to połączenie zachowań z stanem, bo praktycznie każda inna cecha (enkapsulacja czy polimorfizm) nie wywodzi się bezpośrednio z tradycji języków obiektowych. A miks dane <-> zachowania jest tak fundamentalny, że widzimy go zarówno w assemblerze jak i w haskellu.

Dla mnie klasyfikacja powinna być bardziej drobnoziarnista tj. język A wspiera subclass polymorphism a język B wspiera type classy

Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:17 minut
3
slsy napisał(a):

A miks dane <-> zachowania jest tak fundamentalny, że widzimy go zarówno w assemblerze jak i w haskellu.

Kodziłem zarówno w asemblerze (dużo) jak i w Haskellu (mało) i tam obiektówki raczej nie ma (no chyba, że jak robiłem okienka za pomocą win32api). Obiekt jest wtedy, kiedy za pomocą jednego uchwytu (czyli w praktyce referencji) możemy mieć dostęp zarówno do danych jak i funkcji na nich operujących.

Poniższy kod nie jest obiektowy, bo przetwarzajDane nie jest składową typu dane:

Kopiuj
var dane = posklejajDane(arg1, arg2, arg3, ..., argN);
przetwarzajDane(dane);

Poniższy kod jest obiektowy jeżeli metoda przetwarzaj jest polimorficzna (czyli de facto wirtualna):

Kopiuj
var dane = posklejajDane(arg1, arg2, arg3, ..., argN);
dane.przetwarzaj();

Gdyby w powyższym kodzie metoda przetwarzaj była metodą rozszerzającą czy też inną całkowicie statycznie wiązaną metodą to byłoby trochę dyskusyjne czy to bardziej OOP czy może cukier składniowy wyglądający jak OOP. Generalnie zapis xyz.abc() sugeruje prawie wszystkim obiektówkę, a zapis abc(xyz) kod nieobiektowy, ale to moim zdaniem zbytnie spłycanie paradygmatu obiektowego.

Rust ma typeclassy (które akurat w tym języku definiuje się za pomocą słówka kluczowego trait, a nie class jak w Haskellu), ale zamiast typowego dla Haskella zapisu np. sort list oferuje zapis list.sort(). Mimo iż ten zapis z Rusta wygląda jak obiektowy (dla kogoś kto kieruje się powierzchownością, czyli dla zdecydowanej większości programistów) to nadal (pomijając https://doc.rust-lang.org/reference/types/trait-object.html ) pozostaje nieobiektowy, bo opiera się na typeclassach (przy założeniu, że to sort jest polimorficzną metodą, czyli właśnie z typeclassy).

Typeclassy mają sens generalnie tylko przy językach statycznie typowanych (chodzi o sprawdzanie typów na etapie kompilacji, a reified generics nie mają tu znaczenia). Jednym z założeń typeclasses jest to, że się ich jawnie nie podaje (w sensie ich instancji). Zamiast tego to kompilator, na podstawie statycznie obliczonego typu, sam wyszukuje instancje typeclass i podaje je tam gdzie są potrzebne. Dzięki temu kod wygląda jakby struktury danych magicznie nabywały wbudowanych w nie metod, ale tak nie jest. Typeclassy są zadeklarowane (chodzi o interfejs) i zdefiniowane (chodzi o instancje) poza strukturami danych, więc nie ma OOPowego łączenia stanu i zachowania w jeden byt.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 4x, ostatnio: Wibowit
SL
  • Rejestracja:około 7 lat
  • Ostatnio:13 minut
  • Postów:862
0

@Wibowit: ale tutaj mówisz o polimorfizmie. Czy jeśli z Javy usuniemy wszystkie mechanizmy z tym związane (klasa Object, dziedziczenie, interfejsy i tak dalej) to zostanie ona językiem OOP czy nie?

KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:5 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
0

Hm, co zostanie? Klasy z danymi i niepolimorficznymi metodami. Bardzo łatwo zamienić to na klasy z danymi i statycznymi metodami. Różnica będzie tylko w zapisie. dane.metoda() zamieni się na metoda(dane).
Czy to jeszcze jest programowanie obiektowe?


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
SL
  • Rejestracja:około 7 lat
  • Ostatnio:13 minut
  • Postów:862
0

@KamilAdam: Dobre pytanie, sam nie wiem. Inna sprawa, że np. przy kwalifikacji imperatywne vs funkcyjne nie ma takiego problemu: kryteria są proste i łatwo powiedzieć na postawie kodu czy jest on imperatywny, funkcyjny czy oba na raz

Zobacz pozostałe 15 komentarzy
Wibowit
w którym? tym z printem?
Wibowit
jest efekt uboczny w postaci wprost odpalanego printf (w haskellu do tego trzeba byłoby wspomnianego wyżej unsafePerformIO). samo pytanie na stackoverflow było o monady io, których w podanym przykładzie wybitnie brakuje.
somekind
Ok, masz rację. Źle się wyraziłem. Nie o takie efekty mi chodziło.
Wibowit
ale o takie chodziło w tym pytaniu na stackoverflow :)
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10053
1

Nie ma czegoś takiego jak język obiektowo-funkcyjny.

Jeśli w języku istnieje assignment, np można zrobić coś takiego i = 2; i = 3; to nie jest i nie może być funkcyjny. Można w nim napisać funkcyjny kod, po prostu nie używając assignmentów; ale język funkcyjny nie jest, przez to że to dopuszcza. Jeśli natomiast nie ma przypisania, to nie specjalnie można konstrukować obiekty i układać je w hierarchię , więc nie ma mowy żeby był obiektowy.

W skrócie, idea języka "paradygmato-paradygmatowego" nie może istnieć. To jakby powiedzieć że restauracja jest "wegetariańsko-mięsna" albo zadanie jest "łatwo-trudne", ewentualnie ktoś oddał do serwisu telefon "zepsuto-działający".

edytowany 4x, ostatnio: Riddle
Zobacz pozostałe 7 komentarzy
KamilAdam
@hauleth: bo jest mutowalny stan :(
stivens
~kazdy jezyk dostarcza taski mechanizm. Ale w Haskellu np. uzycie go jest minimalne. W Javie natomiast to "co druga linijka"
SL
W takim razie języki funkcyjne nie istnieją. W każdym mogę wywoływać funkcję z C, która odpali wszystkie atomówki na świecie
SL
Co do paradygmatów to nie masz racji, bo paradygmaty to nie występują w przeciwnych parach. Programowanie obiektowe to zupełnie inna dziedzina, nic funkcyjność/imperatywność. Chyba nie powiesz, że Java nie należy do paradygmatu imperatywnego?
hauleth
@KamilAdam: niekoniecznie. Może to być też shadowing. Wtedy masz tylko rebinding nazwy, ale nie ma mutowalności.
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:17 minut
3

@slsy + @KamilAdam
jeśli z javy usuniemy extends (dziedziczenie) i implements (interfejsy), ale zostawimy statyczne typowanie, to zostaniemy z czymś co można nazwać co najwyżej mocno zdegenerowaną obiektowością. nota bene rust oferuje składnię typu zmienna.róbcoś(parametry) (obojętne czy z typeclassy czy nie) oraz oferuje enkapsulację (https://rust-lang.github.io/rfcs/0001-private-fields.html), a więc kierując się samymi tymi aspektami wychodziłoby, że rust jest obiektowy (a generalnie nie jest za taki uważany).

próbowałem sklecić jakąś własną tyradę o esencji obiektowości, ale kręcę się w kółko :) ogólnie ograniczenie się całkowicie do statycznego wiązania sprawia (moim zdaniem), że OOP się mocno degeneruje (teoretycznie i praktycznie). ponadto wikipedia ma ciekawy, chociaż dziwny, podpunkt sugerujący, że OOP mocno polega na dynamicznym wiązaniu:
https://en.wikipedia.org/wiki/Object-oriented_programming#Dynamic_dispatch/message_passing

Dynamic dispatch/message passing

It is the responsibility of the object, not any external code, to select the procedural code to execute in response to a method call, typically by looking up the method at run time in a table associated with the object. This feature is known as dynamic dispatch, and distinguishes an object from an abstract data type (or module), which has a fixed (static) implementation of the operations for all instances. If the call variability relies on more than the single type of the object on which it is called (i.e. at least one other parameter object is involved in the method choice), one speaks of multiple dispatch.

A method call is also known as message passing. It is conceptualized as a message (the name of the method and its input parameters) being passed to the object for dispatch.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
S9
  • Rejestracja:ponad 4 lata
  • Ostatnio:około 2 lata
  • Lokalizacja:Warszawa
  • Postów:1092
0

No bez międzymordzia i dziedziczenia w Javie nie ma polimorfizmu więc to wiadomo co a nie OOP byłoby ;]


Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10053
0
jarekr000000napisał(a):

Praktycznie wszystkie jezyki funkcyjne to po prostu podzbiory istniejących języków wieloparadygmatowych. Funkcyjna scala, funkcyjny haskell, funkcyjny PHP.

Można sobie nawet taki język ładnie skonfigurować korzystając z lintera: tu mój linter, który praktycznie zmusza do pisania czysto funkcyjnego w kotlinie: https://github.com/neeffect/kure-potlin

Mówiłem już. Możesz napisać 100% funkcyjny kod w niefunkcyjnym języku. Nie znaczy to że język jest funkcyjny. Podobnie jak możesz napisać obiektowy kod w nieobiwktowym języku, co nie oznacza że język jest obiektowy. Przykład dla nie-programistów: można zjeść wegetariańskie danie w restauracji, co nie oznacza że restauracja jest wegetariańska.

Funkcyjny język to taki w którym można pisać tylko funkcyjnie, ponieważ język sam to wymusza.

Przy czym od razu wyjaśniam że pojedyncze przypisanie jest totalnie okej. Np w haskellu można przypisać wartośc do zmiennej, let i = 2, ale to tyle.

edytowany 4x, ostatnio: Riddle
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10053
0
slsy napisał(a):

Co do paradygmatów to nie masz racji, bo paradygmaty to nie występują w przeciwnych parach. Programowanie obiektowe to zupełnie inna dziedzina, nic funkcyjność/imperatywność. Chyba nie powiesz, że Java nie należy do paradygmatu imperatywnego

Ja bym powiedział że tzw. "języki hybrydowe" nie należą do żadnego paradygmatu. Skoro można w nich pisać kod taki, taki i sraki, to o żadnym paradygmacie nie może być mowy. Dodawajcie sobie lintery do nich i sprawdzajcie to, wtedy wasze programy mogą się stać obiektowe, funkcyjne, proceduralne lub strukturalne, ale to nie znaczy że język taki jest.

jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:40 minut
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4706
4
TomRiddle napisał(a):

Funkcyjny język to taki w którym można pisać tylko funkcyjnie, ponieważ język sam to wymusza.

Dobra zasada, podpatrzona u matematyków, jest taka, że po takim określeniu zwykle warto podać choć jeden element należący do zbioru. Czy znasz taki język (funkcyjny)?


jeden i pół terabajta powinno wystarczyć każdemu
.andy
Erlang?
hauleth
@.andy: nie. Erlang nie ma żadnego mechanizmu, który wymusza by funkcje były pure. Praktycznie wszystkie funkcje są z natury impure.
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10053
0
jarekr000000 napisał(a):
TomRiddle napisał(a):

Funkcyjny język to taki w którym można pisać tylko funkcyjnie, ponieważ język sam to wymusza.

Dobra zasada, podpatrzona u matematyków, jest taka, że po takim określeniu zwykle warto podać choć jeden element należący do zbioru. Czy znasz taki język (funkcyjny)?

No dla mnie dobrą zasadą kciuka jest to, że jeśli w języku jest assignment zmiennych, np taki i = 2; i = 3; to to nie jest język funkcyjny.

Przy czym od razu mówię że pojedyncze przypisanie, jak np let i = 2 w haskellu, gdzie nie można zadeklarować niezainicjalizowanej zmiennej jest funckyjne imo. To przypisanie ponowne, zmiana czegoś nie jest. Bo w sumie takie zadeklarowania i przypisanie się różni prawie niczym od zdefiniowania funkcji która zwraca stałą.

edytowany 3x, ostatnio: Riddle
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:40 minut
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4706
2

@TomRiddle:
Najpierw rzucasz całkiem ostre definicje, a potem zmieniasz w jakieś reguły kciuka...

Pogrążamy haskell.

Kopiuj
import Data.IORef
import System.IO.Unsafe (unsafePerformIO)
-- zmienna globalna  (!!!) `i`  yolo
i  = unsafePerformIO $ newIORef 0

main::IO ()
main = do
            writeIORef i 2 -- nie ma i = 2, ale mamy setter :-)
            x1 <- readIORef i -- i getter :-)
            writeIORef i 3
            x2 <- readIORef i
            putStrLn $ show $ x1
            putStrLn $ show $ x2

To nawet jest jeszcze mało nieczysty fragment. A można pojechać dużo dalej, rzutować Stringi na Double itd. (unsafePerformIO jest w standardzie (Haskell2010)).


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 1x, ostatnio: jarekr000000
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10053
0
jarekr000000 napisał(a):

Pogrążamy haskell.

Kopiuj
import Data.IORef
import System.IO.Unsafe (unsafePerformIO)
-- zmienna globalna  (!!!) `i`  yolo
i  = unsafePerformIO $ newIORef 0

main::IO ()
main = do
            writeIORef i 2 -- nie ma i = 2, ale mamy setter :-)
            x1 <- readIORef i -- i getter :-)
            writeIORef i 3
            x2 <- readIORef i
            putStrLn $ show $ x1
            putStrLn $ show $ x2

To nawet jest jeszcze mało nieczysty fragment. A można pojechać dużo dalej, rzutować Stringi na Double itd. (unsafePerformIO jest w standardzie (Haskell2010)).

Gdzie tu masz reassignment? Owszem, zmieniłeś wartość tej zmiennej, ale nie ma assignmentu.

zmienna globalna (!!!) i yolo

No i? Mogą być.

edytowany 2x, ostatnio: Riddle
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:40 minut
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4706
1

Gdzie tu masz reassignment? Owszem, zmieniłeś wartość tej zmiennej, ale nie ma assignmentu.

W takim razie mamy inną definicję assignmentu. Dalsza dyskusja nie ma sensu.


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 1x, ostatnio: jarekr000000
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10053
0
jarekr000000 napisał(a):

Gdzie tu masz reassignment? Owszem, zmieniłeś wartość tej zmiennej, ale nie ma assignmentu.

W takim razie mamy inną definicję assignmentu. Dalsza dyskusja nie ma sensu.

Wygodne.

Jak zadeklarujesz sobie stałą w dowolnym języku, to wszyscy się zgodzą że "stałej się nie zmienia w języku programowania". Ale mogę wieloma sposobami zmienić jej wartość, albo metaprogrammingiem, albo formą refleksji, albo edytując pamięć bezpośrednio w ramie. Wiadomo że nie można zrobić PRAWDZIWIE niemutowalnej wartości. Pytanie tylko na co pozwala język, a na co nie.

hauleth
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:10 dni
1

@TomRiddle: w Eliksirze możesz zrobić tak:

Kopiuj
x = 1
x = 2

A mimo to nie masz mutowalności. Dowód?

Kopiuj
x = 1
f = fn -> x end
x = 2

f.() # => 1

Masz tylko shadowing, "pierwsze x" to zupełnie inne x od "drugiego x". Po kompilacji powyższy przykład opowiada Erlangowemu zapisowi:

Kopiuj
X@0 = 1
X@1 = 2

Czy w takim przypadku uważasz, że Elixir to język niefunkcyjny?


Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10053
0
hauleth napisał(a):

@TomRiddle: w Eliksirze możesz zrobić tak:

Kopiuj
x = 1
x = 2

A mimo to nie masz mutowalności. Dowód?

Kopiuj
x = 1
f = fn -> x end
x = 2

f.() # => 1

Masz tylko shadowing, "pierwsze x" to zupełnie inne x od "drugiego x". Po kompilacji powyższy przykład opowiada Erlangowemu zapisowi:

Kopiuj
X@0 = 1
X@1 = 2

Czy w takim przypadku uważasz, że Elixir to język niefunkcyjny?

Nie uważam tego za reassignment, tylko redefinition.

To co się dzieje, to zachowanie które opisałeś, jest dla mnie bardzo funkcyjne. Gdyby f() zwróciło 2, to byłby znak że eliksir jest nie funkcyjny, ale ponieważ zwraca 1 to wszystko jest git i dla mnie to jest funkcyjne.

edytowany 1x, ostatnio: Riddle
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)