Język programowania D - nowa nadzieja czy niewypał

Język programowania D - nowa nadzieja czy niewypał
hauleth
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:11 dni
0

Język programowania D jest statycznie typowanym, kompilowanym językiem wieloparadygmatowym. Pierwsza stabilna wersja pojawiła się w 2007 roku i od tego czasu struktura języka dość mocno ewoluowała. Najważniejsze cechy języka wyróżniające go głównie od C++:

  • prawdziwe moduły, nie ma podziału na nagłówki oraz pliki z implementacją, jednak istnieje możliwość zawarcia interface'u w osobnym pliku
  • brak wielodziedziczenia, zamiast tego mamy interface'y
  • statyczne ify, które są rozwijane w czasie kompilacji
  • samodzielne szablony, co w sumie pozwala na łatwe metaprogramowanie
Kopiuj
template Factorial(ulong n) {
    static if(n <= 1)
        const Factorial = 1; // można zauważyć, że jeśli typ jest określony jako const to jest on określany na podstawie przypisanej wartości
    else
        const Factorial = n * Factorial!(n - 1);
}
  • szablony są określane poprzez !() co pozwala uniknąć problemów jakie są w C++ np. z X< 1>2 > x1. Jednak jeśli mamy tylko pojedynczy argument szablonu można to zapisać jako X!my_func x
  • ujednolicony zapis typów w postaci <typ> <nazwa> oraz brak wielowyrazowych typów jak unsigned int, zamiast tego mamy uint, np.
Kopiuj
uint[] tab; // tablica liczb bez znaku
real pi = 3.14; // liczba typu rzeczywistego
MyClass my_instance; // nie tworzy jeszcze instancji, by ją stworzyć trzeba użyć new MyClass();
my_instance = new MyClass();
string str = "abba"; // string jest aliasem do immutable(char)[] przez co sama tablica jest zmienna, ale nie da się zmieniać poszczególnych znaków
char[] editable_str = str.dup; // edytowalna kopia
const E =2.7182818; // automatyczne określenie typu jako real
idouble imaginary_number = 7.4i; // wbudowane liczby urojone i zespolone
creal complex_number = 15.3 + 3.992i + imaginary_number;
  • silny podział na klasy i struktury
  • wbudowany Garbage Collector
  • możliwość leniwej ewaluacji argumentów, np.
Kopiuj
void my_func(int i, lazy void x) {
    while(--i)
        x();
}

int x = 0;
my_func(3, writeln(x++));
  • wbudowane w rdzeń języka tablice asocjacyjne oraz wektory
Kopiuj
int[string][] table;
table["abba"] = [ 1, 3, 6, 28, 46 ];
table["baba"] = [ 5, 8, 2849, 53 ];
table["abba"] ~= [ 2, 5, 7 ]; // operator ~ służy do konkatenacji tablic
  • programowanie kontraktowe.
Kopiuj
pure int f(int x)
in {
    // sprawdzenie argumentów na wejściu
}
out {
    // sprawdzenie wyjścia
}
body {
    // ciało funkcji
}
  • unit testy zawarte w bloku unittest {}

Co sądzicie o tym wynalazku?


edytowany 1x, ostatnio: hauleth
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 6 godzin
0

A szybsze to niż przynajmniej najnowsze JVMy?

Moim zdaniem prym wiodą języki zarządzane i nie ma się co temu dziwić. C/ C++/ Pascal/ itp są używane generalnie dlatego, aby:

  1. wyciągnąć te kilkadziesiąt procent więcej wydajności,
  2. być w pełni zgodnym z natywnymi API, tzn np w przypadku Javy nie da się wysłać normalnej tablicy po JNI bez narzutu spowodowanego wstrzymaniem GC albo przekopiowaniem tablicy do natywnego bufora,
  3. zredukować zajętość pamięci - konsole dla przykładu mają bardzo mało pamięci, więc tam pakowanie JVMa nie miałoby sensu,

brak wielodziedziczenia, zamiast tego mamy interface'y

Ależ teraz jest parcie na to jednodziedziczenie. Moim zdaniem wielodziedziczenie jest OK, o ile nie wielodziedziczymy stanu, a tylko implementacje metod. Dla przykładu w C# mamy Extension Methods (chyba dobrze napisałem), a w Javie 8 mają być Defender Methods (czyli coś a la Extension Methods, tylko można tam dziedziczyć implementacje, więc jest to rozwiązanie bardziej skalowalne).

Moim zdaniem wielodziedziczenie stanu w C++ to jedna skrajność, a zupełny brak wielodziedziczenia to druga skrajność.


"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.
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:dzień
  • Lokalizacja:Wrocław
0

A co z przeciążaniem i definiowaniem operatorów?

Wibowit napisał(a)

Moim zdaniem wielodziedziczenie jest OK, o ile nie wielodziedziczymy stanu, a tylko implementacje metod.

Moim zdaniem implementacje metod lepiej delegować.

edytowany 1x, ostatnio: somekind
Wibowit
Do czyjego postu się odnosisz?
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 6 godzin
0

Moim zdaniem implementacje metod lepiej delegować.

A to niby dlaczego? Delegowanie to dokładanie niepotrzebnego śmiecia do kodu, tak samo jak rozwlekłe gettery i settery w Javie. Zwłasza jeśli implementacje metod są krótkie, np na jedną linijkę (w jednej linijce w np Scali można naprawdę dużo zrobić).

Myślę sobie o języku w którym można by zrobić dynamiczne wstrzykiwanie implementacji (tzn w locie, nie na etapie kompilacji), coś na wzór:

Kopiuj
SynchronizedSet synchronizedSetObject = nonSynchronizedSetObject with SetSynchronizationSupport

Obecnie można by coś takiego zasymulować właśnie za pomocą delegacji, ale wymaga to sporego nadmiarowego kodu jeśli symulujemy jednocześnie wielodziedziczenie.


"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 2x, ostatnio: Wibowit
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:dzień
  • Lokalizacja:Wrocław
0

Delegowanie, mimo dokładania kodu, daje dużo większą elastyczność niż dziedziczenie.

Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 6 godzin
0

Ta elastyczność jest w małym stopniu wykorzystywana, a powoduje znaczne pogorszenie czytelności. Wg mnie elastyczność kosztem czytelności to zła droga.

Poza tym dynamiczne wstrzykiwanie implementacji nie byłoby praktycznie ani trochę mniej elastyczne niż delegowanie kodu.


"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 1x, ostatnio: Wibowit
hauleth
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:11 dni
0

Aaaaaa, zapomniałem. Zamiast wielodziedziczenia możemy mieć mixiny szablonów. Czyli dajmy na to:

Kopiuj
template MyMixin() {
    void hello(string name) {
        writeln("Hello ", name, "!");
    }
}

class MyClass {
    mixin MyMixin!();
}
// ...
MyClass c = new MyClass();
c.hello();

Co daje efekt podobny do prywatnego dziedziczenia z C++.

Definiować własnych operatorów nie idzie, ale przeciążanie działa w ten sposób, że mamy funkcję opUnary oraz opBinary i one przechwytują wywołania operatorów:

Kopiuj
class MyClass {
    MyClass opUnary(string op)()
    if (op == "!") {
        // implementacja operatora !
    }

    MyClass opBinary(string op)(MyClass c)
    if (op == "~") {
        // implementacja konkatenacji
    }

    int opCmp(MyClass c) {
        // operator porównania, zwraca -1 jeśli większe, 0 jeśli równe i 1 jeśli mniejsze
        // pozwala to na przeładowanie wszystkich 6 operatorów (==, <, >, !=, <=, >=) za jednym zamachem
    }
}

Oprócz tego delegaty i wskaźniki na funkcje mają wręcz debilnie proste typy (w przeciwieństwie do C++)

Kopiuj
int function(int) my_func; // odpowiednik C++ int (*my_func)(int);
int delegate(int) my_delegate;

edytowany 1x, ostatnio: hauleth
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 6 godzin
0

Te mixiny to po prostu moim zdaniem wielodziedziczenie (i to na sterydach bym powiedział), z tym, że przy niejednoznacznościach kod się po prostu nie kompiluje, tzn nie ma mechanizmu obsługiwania niejednoznaczności. A więc nie jest to wielodziedziczenie w ścisłym (tzn Wikipediowym) tego słowa znaczeniu.

W sumie zależy co rozumieć przez wielodziedziczenie. Powinni zrobić jakieś rozróżnienie pomiędzy wielodziedziczeniem, a "wieloimplementacjami", tzn między sytuacją kiedy niejednoznaczności są niedozwolone, a kiedy są. Defender methods z Javy 8 nie wprowadzą w takim razie do Javy wielodziedziczenia w ścisłym tego słowa znaczeniu, ani Extension Methods z C# też nie wprowadzają.


"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 1x, ostatnio: Wibowit
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:dzień
  • Lokalizacja:Wrocław
0
Wibowit napisał(a)

Ta elastyczność jest w małym stopniu wykorzystywana, a powoduje znaczne pogorszenie czytelności. Wg mnie elastyczność kosztem czytelności to zła droga.

W małym stopniu? Delegowanie zwiększa elastyczność i testowalność aplikacji za to zmniejsza błędogenność zmian w kodzie. Praktyczne programowanie obiektowe polega na delegowaniu i komponowaniu, a nie na dziedziczeniu. Nie widzę możliwości napisania przydatnego kodu opartego na dziedziczeniu zamiast delegacji.

Poza tym dynamiczne wstrzykiwanie implementacji nie byłoby praktycznie ani trochę mniej elastyczne niż delegowanie kodu.

Jeśli kod jest napisany obiektowo, tzn. oparty na interfejsach, a nie implementacjach, to nie ma raczej z tym problemu.

winerfresh napisał(a)

Definiować własnych operatorów nie idzie

No to trochę słabo.
A jak z wydajnością?

Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 6 godzin
0

trait Ordered

Możliwość zmiksowania tego traitu do dowolnej klasy jest moim zdaniem bardzo wygodna. Na pewno tworzenie delegatów tutaj nie ma najmniejszego sensu.

Generalnie takie twoje gadanie jest identyczne z gadaniem twórców Javy i jej pierwszymi piewcami. Twierdzili oni, że za pomocą interfejsów da się elegancko załatwić wszystko co tylko możliwe. Tyle, że teraz nawet sam ojciec Javy chwali Scalę, która przecież ma wielodziedziczenie. Poza tym programowanie obiektowe nie wymusza pojedynczego dziedziczenia.


"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.
R9
  • Rejestracja:ponad 14 lat
  • Ostatnio:ponad 10 lat
0

Język D w wersji 2.0 pozwala na przeciążanie operatorów, robi się to trochę inaczej niż w C++:
http://www.digitalmars.com/d/2.0/operatoroverloading.html
Własne może się da używając innych stringów. Może dodadzą.

Niegłupie by było wsparcie dla nagłówków i klas C++, ale pomarzyć można. Przydałyby się biblioteki pod ten język, bo sam podobnie jak c++ wiele nie oferuje, ale jest od niego o wiele wygodniejszy.

edytowany 1x, ostatnio: Razi91
hauleth
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:11 dni
0

@Razi91 wsparcia dla nagłówków z C++ nigdy nie zrobią, tak samo jak nie ma wsparcia dla C. Nie da się iść do przodu cały czas trzymając się spódnicy mamusi co twórcy D zauważyli, dlatego zrezygnowali z tej "dogodności". Współpraca jest jedynie na poziomie binarnym co daje możliwość portowania bibliotek, ale trzeba jednak zrobić ten interface w D.
Własne operatory może i by się czasem przydały, ale to jest raczej domena języków funkcyjnych. Osobiście nie za bardzo odczuwam taką potrzebę by móc definiować własne operatory, choć patrząc na aktualny sposób definiowania operatorów, nie zdziwił bym się jak by taki feature powstał.

Porównanie szybkości (jakieś tam marne):
C++ http://ideone.com/G0lNO
D http://ideone.com/rg6lf (niestety nie da się użyć v1[i][] * v2[i][] z niewiadomych mi powodów, być może ze względu na to, że są to tablice statyczne :/)


edytowany 1x, ostatnio: hauleth
Zobacz pozostałe 3 komentarze
Wibowit
Tyle tylko, że tych matematycznych znaczków ciągle przybywa. Widziałeś gdzieś klawiaturę, do której można dokładać coraz więcej klawiszy?
somekind
Podejrzewam, że do 95% przypadków wystarczyłyby nawet te z XIX wieku, bo teraz nie ma nawet jak zrobić operatora transpozycji macierzy ani iloczynu wektorowego (skalarnego zresztą też nie). Operator modułu to też byłoby coś, bo chyba nigdzie nie ma operatorów, między które wstawia się zmienną. ;)
somekind
A co do rozszerzalnych klawiatur - już teraz chyba można dokupować moduły numeryczne do klawiatur Apple. A jeśli zrobiłoby się klawiaturę "matematyczną", to można by i o rozszerzalność zadbać, jeśli faktycznie jest taka potrzeba. Bo w sumie nie zauważyłem jakichś nowych znaczków w ostatnim czasie.
ZJ
@somekind: oczywiście w wolnym czasie śledzisz najnowsze artykuły w pismach matematycznych.
somekind
@Zjarek, masz całkowitą rację, z tymże ja nie mam wolnego czasu. :P
hauleth
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:11 dni
0

Był by jakiś admin skłonny dodać ankietę do tematu?


vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
0

Język D ma wiele ciekawych pomysłów, bardzo użytecznych, ale dla mnie ten język jest trochę niespójny.
Im dłużej go poznaję z takich opowieści tym bardziej przypomina mi on listę przedwyborczych obietnic a nie język.

Kilka z tych pomysłów powyżej można stosować w C++:

Kopiuj
typedef unsigned int uint;

)

  • co do delegatów to w C++ też są już proste:
Kopiuj
boost::function<int (const char*)> f = std::atoi; 

Ogólnie język nie jest zły, tylko jak wygląda jego integracja ze światem? Tzn: GUI, Win32 API, bazy danych, języki skryptowe (Python)?

edytowany 1x, ostatnio: vpiotr
hauleth
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:11 dni
0

Przede wszystkim typedef w C++ i w D to zupełnie inna liga. Do wszystkiego były biblioteki, ale niestety większość z nich została zawieszona lub porzucona, jednak zawsze istnieje możliwość użycia bibliotek C (choć jeśli chodzi o WinAPI to chyba std.c.windows zawiera już gotowe deklaracje).
@vpiotr masz rację, ale jednak by użyć delegata w taki sposób jak ty napisałeś potrzebna jest dodatkowa biblioteka a tu mamy wszystko w rdzeniu. A czemu niby lista obietnic przedwyborczych, większość z tego co jest opisane jest zaimplementowane i działa przewidywalnie i poprawnie. Osobiście uważam, że jedyną rzeczą w jakiej ustępuje C++ jest brak popularności.


Endrju
std::function jest w C++11.
vpiotr
Ponieważ lista obietnic też jest niespójna. Ale oczywiście zakładam że to co jest udokumentowane dla D działa i jest przetestowane. To tylko komentarz jak to wygląda na pierwszy rzut oka - trochę C, trochę Pascal / Delphi (property, finally, pod-funkcje, konstruktor nazwany ogólnie - tak samo dla wszystkich klas), koncepcja modułu nie wiadomo z jakiego języka...
hauleth
Moduły: Java/C# finally: praktycznie każdy szanujący się język posiadający wyjątki pod-funkcje: Pascal, JavaScript, Ada Konstruktor nazwany ogólnie: Ruby, Python, PHP To tak by przedstawić co i jak. Ale zobacz, że każdy praktycznie język się na czymś wzorował, w prawdzie są rewolucyjne wyjątki (Lisp, Smalltalk, Haskell) ale należą one do rzadkości. Jak niespójna? Bo nie rozumiem co w niej jest niespójnego.
vpiotr
Moduły w tej formie - nie wiem skąd czerpał pomysł autor, bo na pewno nie z Pascala, Moduli, Pythona. Brakuje np. sekcji prywatnej i publicznej, chyba że czegoś nie doczytałem - http://bit.ly/o5VMDB Poza tym reszta wymienionych przeze mnie rzeczy jest w Delphi / Pascalu. No i ten writefln - w stdio ;-) . Jedna bazowa klasa (Object) - też Pascal. Widać że autor znał Pascala i wkurzył się na zaszłości C/C++.
hauleth
Akurat jedna główna klasa po której wszystko dziedziczy to pomysł Smalltalk'a. Nie doszukałem się enkapsulacji na poziomie modułów ale zawsze można zrobić osobny moduł, dać go jako private import.
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)