No tak podejrzewałem, że chodzi o NaN
, tylko nadal nie czaję, w jaki sposób + + 'a'
się zamienia w NaN
. Bo albo traktujemy to jak resztę, czyli jako string, albo puste pole między plusami jest NaN
, ale dalej mamy a
, które powinno się dokleić do ostatniego A. Zgodnie z moim rozumieniem sprawy powinno być B A NAN A A
Ale czemu większość liter jest traktowana jako string/char i są wykonywane na nich operacje testowe, a pusty fragment pomiędzy 2 i 3 plusem nie jest traktowany jako pusty string, tylko staraja się go na numer przerobić?
@cerrato: drugi plus wszystko psuje bo próbuje zmienić 'a'
na numer a jak mu się nie udaje to wychodzi NaN ;-)
@cerrato Dodawanie zmiennych do stringu, automatycznie wykonuje konwersje do stringu (toString). '12' + 4
dałoby '124'
.
A dodanie pustego objektu: '12' + {}
dałoby '12[object Object]'
Aby uzyskać 14 trzeba zmienić '12' na number poprzez Number('12')
lub +'12'
.
Dlatego też + 'a'
daje NaN a następnie jest to dodawane do stringa. Stąd potrzebne są 2 plusy, a spacja pomiędzy nimi nic nie znaczy. Spacja to tylko spacja i mogłoby jej być tysiące.
A czemu drugi plus psuje? Czy może on nie jest traktowany jako operator łączenia tekstów - czyli nie należy tego rozumieć jako B + A + NIC + A
, tylko raczej ten znak plus oznacza, że ```do B + A dodaj +A" - czyli wartość dodatnią "A". Ponieważ "A" nie jest liczbą, nie można go przerobić na numer, więc wyskakuje NaN?
I swoją drogą - jakie to jest chore, jakieś zgadywanki itp. Dlatego nie lubię języków luźno typowanych. W innych to by nie miało racji bytu, bo już na etapie kompilacji/parsowania by wyskoczył błąd. Jeśli chcesz zmienić string
na liczbę albo odwrotnie to trzeba wpisać wprost toStr
albo toInt
, inaczej nie przejdzie. I nie ma takich zagadek jak powyższa,
Drugi nic nie psuje, jeden zmienia string na number i powstaje NaN, a drugi dodaje to do stringu :)
No i najlepsze, że w typescript możesz pisać wszędzie tam gdzie js, bo ts to tylko superset języka js. Zyskujesz wygodę, nic nie tracisz.
Daję plusa bo hejt na JS zawsze cenię. Chciałbym poznać człowieka który wymyślił żeby dodawać stringi za pomocą '+' :] . Nawet Java/Scala/Kotlin są tym zepsute :(
@Aryman1983: Ale często jest to rozwlekłe rozwiązanie. W Perlu, Lua jest ..
. W Haskellu jest ++
. Naprawdę można było to zrobić w prosty sposób lepiej
To jest nic, ja jedną linijką kodu w js potrafię coś wydrukować drukarką (o ile jest podłączona).
W tym momencie rozumiem domowego kota na pustyni: - Nie ogarniam tej kuwety :-o
Ups :) To już rozumiem czemu się tak dziwicie. Ja niedawno czytałem jakiś stary wątek i na to trafiłem. Nie spojrzałem na rok tylko na miesiąc.
@cerrato: To nie jest problem samego luźnego typowania a kontekstu w jakim można użyć wyrażenia. Takie kwiatki można znaleźć też innych językach, np. w Javie czy C++.
i co ciekawe wystarczy usunąć spacje między dwoma plusami i dostaniecie SyntaxError
@PerlMonk: To jest problem luźnego typowania, niestety Java jeśli chodzi o typ String i operator +
zachowuje się jak luźnotypowany język (automatyczne konwersje do typu String). W Scali udało mi się to kiedyś ogarnąć za pomocą lintera i wtedy nie mogłem napisać "string " + 5
. Musiałem pisać "string " + 5.toString
co jest IHMO o wiele lepszym rozwiązaniem. Niestety nie jest to zachowanie domyślne w Scali :(
@PerlMonk Takie kwiatki można znaleźć też innych językach, np. w Javie czy C++
- w takim razie proszę o przykład w Pascalu :P
A nie lepiej formatowac zamiast konkatenowac?
a to nie jest cofanie się do czasów C? Zresztą w niektórych językach formatter stringów nie jest nawet w bibliotece standardowej :D
@perlmonk - czyli nie masz nic sensownego do dodania :P Wiem, że Pascal i pochodne są mało fancy & sexy
, ale rygor w nich zachowany tutaj okaże się zbawienny. Po prostu - fizycznie nie ma opcji, żeby takie coś przeszło, bo wywali się na etapie kompilacji. Zmienne mają typy i nie ma opcji żeby zrobić 'C' + 12
.
@cerrato: Ale to samo możesz powiedzieć o asemblerze, Fortranie czy innych, które nie mają operatora inkrementacji. Jak chcesz porównać działanie inkrementacji w języku, który tego operatora nie ma?
@PerlMonk: Chyba nie nadążam, co ma inkrementacja do konkatenacji napisów?
@cerrato: Ta linijka była w pliku.html na przykład index.html, wtedy dodawałeś <script> i w tym miejscu żeby kod o coś zapytał i póżniej ifa jeżeli to o co zapyta jest poprawne, następnie print("tekst do wydrukowania") </script> i działało, tylko trzeba było wybrać drukarkę, niestety sprawdziłem teraz i mi nie działa :/.
Zresztą Perl ma operator inkrementacji, a powyższy problem tam nie występuje. Dlaczego? bo jest osobny operator do dodawania liczb, a osobny do konkatetacji napisów
@KamilAdam: No właśnie, Perl ma - tak samo jak wspomniane przez szczurka luźne typowanie. W Perlu jednak masz inne podejście związane z kontekstem wyrażenia i typem danych.
No ale nie musi być odmiennego operatora do stringów i numerków, jeśli rodzaj operacji wynika z kontekstu oraz typu operandów. W językach mocno typowanych w ogóle nie będzie miał znaczenia kontekst, bo same typy argumentów będą wystarczające.
Też tak może być. Ale np. w Perlu reprezentacja zmiennej zależy od typu danych i kontekstu. Jeśli masz liczbowy typ danych (to nie typ zmiennej!) to możesz go użyć jako liczbę i jako string - jest to zależne od kontekstu. To, co napisał @KamilAdam o operatorach... to też nie jest taka prosta sprawa, bo operatorowi dodawania też można dodać działanie w danym kontekście. W każdym razie wracając do typowania: nie trzeba wymuszać deklaracji typu zmiennej, żeby uniknąć takich nieporozumień. Perl po to używa wszystkich znaków jakie masz na klawiaturze (tak, naprawdę tak jest), żeby móc wyjaśnić tego typu sprawy.
@KamilAdam: Nie widze tutaj zadnego cofania sie do czasow C. Moze niektore jezyki nie maja tego w bibliotece standardowej ale w Scali tak jak w Kotlinie masz chyba jakies "1 + 1 = ${1+1}"
@Aventus: To akurat słaby przykład bo te funkcje przyjmują argumenty, Math.min([value1[, value2[, ...]]])
i Math.max([value1[, value2[, ...]]])
.
Dlatego dla Math.min() wychodzi Infinity a dla Math.max() -Infinity ;)
@MasterOf: przecież wszystko da się wyjaśnić mechanizmami JS, nic magicznie się tam nie dzieje- tak samo jak np. z bananem. Rzecz nie w tym dla czego JS zwraca taki a nie inny wynik, tylko w intuicyjności kodu. W tym cała zabawa przecież :)
Cóż wypada mi być uczciwym w swoim hejcie na JS i przyznać że zachowanie funkcji min
i max
w JS jest intuicyjne. O ile tylko się zrozumie że min
i max
przyjmują varargs (czy jak tam się nazywa lista reprezentująca zmienną ilość parametrów w JSie)
Proszę sobie nie żartować z poważnych spraw. Funkcja to jest coś, co ma dziedzinę i przeciwdziedzinę, w tym wypadku nie mamy nawet dziedziny, więc ja nie wiem co to jest, może np. ziemniak albo zepsuta pralka, ale na pewno nie funkcja. Nie jest to też funkcja pusta, bo taka musi być unikalna w zbiorze, a tutaj mamy dwie. No chyba, że to tylko aliasy na jedną funkcję pustą, ale czemu w takim razie wyniki różne?
Im bardziej racjonalnie próbuje się to wyjaśnić, tym więcej absurdu.
@KamilAdam: No nie wiem. Jeśli mam funkcje zwracające minimalną i maksymalną wartość, to spodziewał bym się że dla braku wartości wejściowych obie funkcje zwrócą albo tą samą wartość, albo że Math.max()
będzie większe od min()
. Wyobraźmy sobie że sami piszemy taką funkcję zwracającą maksymalną liczbę- chyba najlogiczniejszą decyzją dla braku wartości wejściowych było by zwrócenie albo domyślnej wartości dla typu numerycznego (w .Net np. 0 dla int
) albo coś reprezentującego brak wartości, np. null
. Od kiedy domyślną największą wartością z pustego zbioru wartości jest nieskończoność? Tłumaczenie O ile tylko się zrozumie
też niezbyt tutaj pomaga. Ja bym mógł stworzyć funkcję min()
która w rzeczywistości zwraca największą wartość ze zbioru, i też tłumaczyć to tym że "o ile tylko się rozumie" że min zwraca max to wszystko jest cacy.
Cały myk z intuicyjnością kodu polega na tym żeby można było przewidzieć jego zachowanie bez zagłębiania się w szczegóły implementacyjne. Bo jeśli w takie szczegóły się zagłębiamy to już nie mówimy o intuicyjności tylko przewidywaniach opartych na znajomości tych szczegółów.
Hm, na szybko sprawdziłem kilka innych języków skryptowych (Lisp, Scheme, Racket, Python, Ruby, Perl) i wszystkie za wyjątkiem Ruby i Perla dla pustej listy argumentów zgłaszają błąd. Ruby zgłasza nil
, Perl zwraca pustego stringa :D
@Aventus: jak piszesz samemu taką funkcję to piszesz to tak:
function min(arr) {
let min = MAX_POSSIBLE_VALUE
for (let elem in arr) {
if (elem < min) min = elem
}
return elem
}
W takiej postaci staje się to oczywiste dlaczego Math.min()
zwraca Infinity
dla pustej listy argumentów.
@hauleth: no ale właśnie takie podejście jest wbrew intuicji i w zasadzie również wbrew logice. Nie wiem czemu ma służyć Twój przykład. Temu jak to jest zrobione w JS? Nikt nie kwestionuje tego jak to jest zrobione bo tak jest i tyle. Natomiast jak najbardziej jest to nie intuicyjne, tym bardziej że jak wypunktował @KamilAdam inne języki z takimi kwiatkami nie wyskakują. Czy ja naprawdę pisze niewyraźnie o różnicy między tym co intuicyjne a tym co jest wiedzą o szczegółach implementacyjnych? Co tu ciężkiego do zrozumienia?
@Aventus: Dobra, już. Przyznaj się do błędu i tyle. Nie ma co przeciągać struny
grzesiek51114Tak to jest gdy wchodzisz na sztywną celę, nie potrafiąc grypsować.