Czy czyste funkcje mogą przyjmować argumenty tylko przez wartość?

Odpowiedz Nowy wątek
2019-08-16 17:04
2

Przejrzałem internet i obecnie mam następującą definicję czystej funkcji (niezależnie od języka programowania):

  1. Zwracana wartość (jeśli ją ma?) zależy wyłącznie od jej argumentów. — Mówiąc kolokwialnie, nie czyta z obiektu dostępnego z zewnątrz. [wykreślone, bo błędne]
  2. Nie posiada skutków ubocznych (side effects). — Mówiąc kolokwialnie, nie pisze do obiektu dostępnego z zewnątrz. [wykreślone, bo być może błędne]

Jednak zastanawia mnie pewna rzecz: z uwagi na punkt nr 1 wszystkie funkcje, które przyjmują argumenty przez referencję, nie będą czyste.

Dedukując, za czystą można uważać jedynie funkcję przyjmującą argumenty przez wartość.

Dobrze myślę?


UPDATE: Przykład w języku JavaScript:

// Funkcja, która moim zdaniem jest czysta według powyższej definicji
//    - liczby przekazywane są przez wartość *
function(someNumber) {
    return someNumber + 1;
}

// Funkcja, która moim zdaniem nie jest czysta według powyższej definicji
//    - obiekty przekazywane są przez referencję *
function(someObject) {
    return someObject.someProperty;
}

UPDATE2: * W języku JavaScript funkcje generalnie uznawane są za takie, które przyjmują argumenty przez wartość (np. według tej dokumentacji MDN), ale najpewniej nie o takie rozróżnienie mi chodzi. MDN podaje, że "object references are values". Dlatego też pominąłem to rozróżnienie wyżej.


edytowany 13x, ostatnio: Silv, 2019-08-17 00:50

Pozostało 580 znaków

2019-08-16 17:20
1

Dobra nie za bardzo rozumiem.
Zakładając że mamy takie coś w Javie:


List<String> words = ImmutableList.of("Hello", "There");

//blablabla

public static final int sumOfStringLenght(List<String> strings) {
  return strings.stream()
    .mapToInt(String::length)
    .sum();
 }

Jest to przekazanie wartości referencji, nie wartości prymitywnych(zakładając że o to Ci choddzi), ale na pewno jest to czysta funkcja, bo przecież dla takiej samej listy String będzie zawsze ten sam rezulat


Nie pomagam przez PM. Pytania zadaje się na forum.
edytowany 1x, ostatnio: scibi92, 2019-08-16 17:20

Pozostało 580 znaków

2019-08-16 17:22
0

@scibi92: nie na pewno jest to czysta funkcja. Lista może się zmienić niezależnie od funkcji, a referencja do niej nie musi. Według powyższej definicji nie jest czysta. Właśnie w moim pytaniu chodzi o to, czy ta definicja jest poprawna. Jeśli nie jest, prosiłbym (w pierwszej kolejności) o podanie jakichś źródeł, które mówią, że funkcje czyste mogą przyjmować argumenty przez referencję.


edytowany 3x, ostatnio: Silv, 2019-08-16 17:25

Pozostało 580 znaków

2019-08-16 17:27
0

In computer programming, a pure function is a function that has the following properties:[1][2]

Its return value is the same for the same arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams from I/O devices).
Its evaluation has no side effects (no mutation of local static variables, non-local variables, mutable reference arguments or I/O streams).

Moim zdaniem jednak jest to czysta jak łza funkcja, dla takiej samej listy zawsze rezultat będzie ten sam, a czytając kolejne wartości nie zmienamy orginalnej listy. Czyli
1)ten sam rezultat dla tej samej listy
2)żadnych efektów ubocznych
Dla mnie wszystko gra i buczy


Nie pomagam przez PM. Pytania zadaje się na forum.

Pozostało 580 znaków

2019-08-16 17:28
0

@scibi92: rozumujesz w większości poprawnie, zgodzę się. Ale zauważ, że piszesz: ten sam rezultat dla tej samej listy. Tak by było, gdyby lista nie mogła się zmieniać. Ale może się zmienić, a referencja do niej pozostanie ta sama. W ten sposób dwa wywołania powyższej funkcji przedzielone zmianą listy (nie zmianą referencji do niej) zwrócą inne wartości.


UPDATE: Tak się zastanawiam... w zasadzie nie ma sensu mówić o liście, skoro przekazujemy referencję do niej. Chyba więc odpowiedź na moje pytanie jest: nie muszą tylko przez wartość.


edytowany 2x, ostatnio: Silv, 2019-08-16 17:30

Pozostało 580 znaków

2019-08-16 17:32
2

funkcja nie zmienia listy wiec jest czysta. to ze probojesz sobie strzelic w kolano to tylko twoja wina ;)

Ja tak mam, za dużo myślę czasem. ;) - Silv 2019-08-16 17:32

Pozostało 580 znaków

2019-08-16 17:34
0

Czyli, idąc tropem z mojego poprzedniego postu – wszystkie funkcje przyjmujące argumenty przez referencję (poza obostrzeniami dla funkcji czystych) będą czyste.


edytowany 1x, ostatnio: Silv, 2019-08-16 17:34

Pozostało 580 znaków

2019-08-16 17:34
1

No masz rację, ale tutaj ale nawet dla mutowalnego argumentu jest to moim zdaniem czysta funkcja. A moim zdaniem mówiąc o argumencie mamy na myśli po prostu wartość, czyli dla refencji to będzie wartośc Seta, Listy, Mapy czy jakiegoś DTOsa - tutaj mamy ta samą wartośc listy. No i poza tym może być referencja do obiektu niemutowalnego ;)


Nie pomagam przez PM. Pytania zadaje się na forum.
Jakkolwiek na swoje pytanie sam sobie odpowiedziałem, to chciałbym zaznaczyć, że raczej nie masz racji. W przypadku referencji, wartość w moim rozumieniu jest referencją (lub wskaźnikiem, jeśli dany język wyodrębnia wskaźniki), nie obiektem, na który ona (on) wskazuje. - Silv 2019-08-16 17:36
@jarekr000000: a co Ty byś powiedział - scibi92 2019-08-16 17:43

Pozostało 580 znaków

2019-08-16 17:37
2

@Silv mysle ze takie rozkminy sa wartosciowe, niemniej nie ma co popadac w skrajnosci. mowiac o "czystosci" operujemy na pewnym poziomie abstrakcji, wiadomo ze przy roznych ekstremalnych warunkach (np dzgnieciu srubokretem w cpu) moga wystapic efekty uboczne, ale z punktu widzenia jvm taka funkcja efektow ubocznych nie ma.

Pokaż pozostałe 10 komentarzy
@Silv no na poziomie maszyny wirtualnej czy UX nie będzie czysta (szczególnie, że nadmierna alokacja pamięci może mieć realne skutki dla aplikacji, RAM, garbage collector itp.), ale koncepcyjnie myślę, że alokacja pamięci może być czysta, bo inaczej nie dałoby się zwrócić obiektu () => ({}) -- następuje alokacja pamięci na obiekt. Zresztą też nie wiemy do końca jak działają VM pod spodem. Był kiedyś bug w V8 w którym robienie czegoś, co nie powinno mieć skutków ubocznych - miało takie skutki. Ale myślę, że funkcja w rozumieniu VM jest czymś innym niż funkcja koncepcyjna. - LukeJL 2019-08-16 18:03
@Silv to https://www.reddit.com/r/java[...]s_be_warned_about_this_crazy/ w zasadzie tu i tak jest skutek uboczny, bo console.log, ale pomińmy to. W każdym razie VMki coś dziwnego robią zawsze w tle, o których sami twórcy nie mają pojęcia jak widać (V8 jakieś optymalizacje podobno robi sobie cały czas, które są triggerowane przez same wywoływania funkcji. Więc nawet czyste funkcje mają jakieś skutki uboczne z perspektywy całego systemu) - LukeJL 2019-08-16 18:07
@LukeJL: ciekawy przykład z tym zwracaniem obiektu w JS. Coś jak alokacja pamięci... choć ja bym powiedział raczej, że to wywołanie konstruktora Object(), czyli innej funkcji (nie wiem, jak to jest rozwiązane pod spodem). - Silv 2019-08-16 18:09
no dobra, ale pamięć się alokuje, bo gdzieś te obiekty muszą być trzymane (zresztą można to zobaczyć w dev toolsach z Chrome, gdzieś jest taka opcja, że pokazuje alokowane obiekty i ile pamięci zajmują) . - LukeJL 2019-08-16 18:46
@Silv: chyba częściej jednak w statkach kosmicznych masz takie single bit upset. W CERNie za to są UFO https://cds.cern.ch/record/2063441/files/LHCReport_1_image.png ;) - Shalom 2019-08-16 22:40

Pozostało 580 znaków

2019-08-16 17:38
1

W językach funkcyjnych listy są często immutable więc jeżeli masz 2 referencje i obie są takie same to masz pewność, że chodzi o listę z tymi samymi bebechami pod spodem. Jeżeli zmodyfikujesz taką listę w jakikolwiek sposób to stworzysz nową referencję więc będziesz miał pewność, że lista już nie jest taka sama. Tym samym wywołanie funkcji z konkretną referencją na listę jako argumentem zawsze zwróci ten sam wynik.

edytowany 1x, ostatnio: twoj_stary_pijany, 2019-08-16 17:39
A, umknęło mi to o nowej referencji. Ważna rzecz, dzięki za zauważenie. - Silv 2019-08-17 00:14

Pozostało 580 znaków

2019-08-16 17:42
0

Tylko dalej się zastanawiam (@twoj_stary_pijany, niezależnie od tego, co napisałeś): jaki jest sens wyodrębniania takich funkcji czystych? Skoro mogą przyjmować argumenty przez referencję, to w rozumieniu "ogólnym" dwa wywołania funkcji nie będą zwracały takich samych wartości. Dlaczego? Bo jak przekazuję obiekt "Słoń", to nie obchodzi mnie, jaka jest do niego referencja, a raczej jaki jest on sam... czy też referencja także obchodzi? Czyli w ten sposób wyodrębnianie funkcji czystych powinno następować nie na poziomie "obiektowym" (uogólniając pojęcie "obiektu"), tylko na poziomie, hm... mechanizmów danego języka?


Ani w Javie, ani w JS nie jesteś w stanie stworzyć czystych funkcji funkcyjnych. Są to języki wieloparadygmatowe, czyli żadnego paradygmatu nie implementują poprawnie. Muszą iść na kompromisy. - twoj_stary_pijany 2019-08-16 17:43
Czyli w takim razie uznanie funkcji za czystą lub nie zależałoby od mechanizmów danego języka, a nie od jakiegoś wyższego poziomu abstrakcji? - Silv 2019-08-16 17:45
W zasadzie w Javie jesteś stworzyć funkcje czyste jeżeli parametry są immutable. Np. fun(String a) będzie funkcją czystą o ile nie dociąga sobie danych z innych źródeł. Ale w ogólności Java nie jest językiem czystym funkcyjnie, a sama mutowalność jest mechanizmem języka. - twoj_stary_pijany 2019-08-16 17:47

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0