Rust 1.0.0-alpha

Odpowiedz Nowy wątek
2015-01-27 22:20
6

Zacznę od zacytowania Niklausa Wirtha:

I would love to see somebody tackle the challenge of demonstrating that you can create a portable systems language (meaning that it has performance equal to C, C++, Fortran) that is portable, type safe, and also memory safe. To add that on top of classes and templates and the portability of C, to add strong type safety (which requires a form of garbage collection) and not leave performance on the table – that would be something.

No i można powiedzieć, że wszystkie te "cele" są w trakcie realizacji przez Rusta. Oczywiście wiąże się to z pewnymi kosztami:

  • nie jest to język dla początkujących (mimo w miarę intuicyjnych podpowiedzi kompilatora)
  • lifetime i ownership potrafi przysporzyć trochę problemów nawet bardziej zaawansowanym programistom
  • jak na razie dość długie czasy kompilacji
  • mocne typowanie potrafi przysporzyć problemów (np. fn add2<T>(a: T) -> T where T: Float { a + 2.0 } nie zadziała, trzeba użyć [o zgrozo] fn add2<T>(a: T) -> T where T: Float { a + cast(2.0).unwrap() }, jednak mam nadzieję, że to niedługo poprawią)
  • łatwo napisać kod, który niespecjalnie będzie wydajny, przez multum wywołań clone

Jednak w przeciwieństwie do innych ostatnio "nowych" języków (jak Go czy D) ma wiele usprawnień:

  • brak null, zamiast tego mamy enum, który działa podobnie jak type w Haskellu
  • proste FFI
  • bezpieczeństwo pamięci w czasie kompilacji (brak GC)
  • wbudowane wsparcie dla wielowątkowości i SIMD
  • typy Hindley-Milner'a, przy których auto z C++ jest śmieszne
  • aktywne budowanie społeczności już w czesnych stadach rozwoju (via Reddit, Discourse i Cargo - manager paczek i build tool)
  • szybkość (wiadomo, idealnie nie jest, ale patrząc na wersję języka to i tak można powiedzieć, że jest nieźle)
  • brak dziedziczenia, w zamian dostajemy system traits, który działa podobnie jak w Scali
  • szablony z constraintsami
  • makra składniowe i rozszerzenia kompilatora (zaczerpnięte z Lispów)
  • wbudowane krotki
  • destructive assignment
  • immutability by default
  • pattern matching

Hello World (bo być musi, potem napiszę jakiś dłuższy przykład):

fn main() {
  println!("Hello World!");
}

Co o tym sądzicie? Ma ten język szansę na zajęcie swojego miejsca w niszy gdzie teraz jest C/C++? IMHO ma szansę na ograniczenie roli C++, bo C zawsze będzie jako uniwersalny język do FFI.

Materiały:

edytowany 2x, ostatnio: hauleth, 2015-01-29 13:43

Pozostało 580 znaków

2015-01-27 23:00
1

Opis wygląda zachęcająco. Pobawię się tym językiem przy wolnej chwili i napiszę później jakie mam spostrzeżenia.

Pozostało 580 znaków

2015-01-27 23:07
0

Koncepcje mają fajne, ale bez dziedziczenia (i interfejsów) to ja temu projektowi nie wróżę długiej kariery.
No i jeśli nie null to powinien być przynajmniej jakiś optional:
http://docs.oracle.com/javase[...]s/api/java/util/Optional.html

Szczerze mówiąc to przydałby mi się jakiś język do HPC który by nie wymagał stosowania 5-ciu paradygmatów (C++), byłby spójny (trochę jak Java) i nie okraszony setką słów kluczowych (C#).


Szacuje się, że w Polsce brakuje 50 tys. programistów
Interfejsy są - traits. Nie ma tylko dziedziczenia w ścisłym tego słowa znaczeniu. - hauleth 2015-01-28 00:58

Pozostało 580 znaków

2015-01-27 23:27
2

To coś jest nawet mniej czytelne niż C++. Już nawet podstawowe typy są całkowicie nieczytelne. To spore osiągnięcie. Wymyślił to chyba jakiś miłośnik skrótów, który dalej myśli, że pracujemy na terminalach z 80 znakami w wierszu. fn i8, str, pub, wtf?

Tu jest jeszcze kilka setek innych epokowych wynalazków: http://en.wikipedia.org/wiki/List_of_programming_languages Tylko jakoś... nie wyszło im. Z tym będzie tak samo, jak z każdym innym od dawna. Ja nie jestem przekonany, czy potrzebujemy 6 nowych, nikomu niepotrzebnych, przełomowych języków na rok. Nie prościej się skupić na ewolucji tych, które już są? Wiadomo, że nie można mieć jednego języka do wszystkiego. Ale wydaje się, że mamy już kilka (-naście?), które pokrywają zdecydowaną większość potrzeb. Reszta to egzotyka. :-)

xkcd napisał(a)

Situation: There are 14 competing standards.
Cueball: 14?! Ridiculous! We need to develop one universal standard that covers everyone's use cases.
Ponytail: Yeah!
Soon:
Situation: There are 15 competing standards.
(http://xkcd.com/927/)

PS. Tak, jestem pesymistą. Tak, jestem marudą. :-P


"(...) otherwise, the behavior is undefined".
edytowany 4x, ostatnio: Endrju, 2015-01-27 23:37

Pozostało 580 znaków

2015-01-28 01:17
0

@Endrju tylko problem polega na tym, że jak Ruby i Python są w większości wobec siebie redundantne, Go vs OCaml też można by tak określić. Jednak Rust wprowadza parę konceptów do programowania systemowego, o których nikt wcześniej nie myślał (pattern matching i HMTS). Choćby to może spowodować pewne zainteresowanie. Co do typów to trochę się zgodzę, ale nie do końca. IMHO zbytnio różnicy między uint32 a u32 nie ma, zwłaszcza jak masz podświetlanie składni. Kolejną rzeczą jest to iż nie za często używa się typów, bo w większości przypadków kompilator sam potrafi określić potrzebny typ (poza deklaracją funkcji praktycznie się tego nie używa).

vpiotr napisał(a):

Koncepcje mają fajne, ale bez dziedziczenia (i interfejsów) to ja temu projektowi nie wróżę długiej kariery.
No i jeśli nie null to powinien być przynajmniej jakiś optional

Ma typ Option. Jest on zdefiniowany mniej więcej tak:

pub enum Option<T> {
  Some(T),
  None
}

I jest używany np. w iteratorach (iteracja trwa tak długo, aż nie zostanie zwrócone None).

Co do "interfejsów" to są traitsy, które działają w taki sam sposób, i.e.:

trait Foo {
  fn foo(&self);
}

struct Boo;

impl Foo for Boo {
  fn foo(&self) {
    println!("Boo#foo");
  }
}

Kolejną rzeczą, o której zapomniałem jest brak wyjątków. Zamiast tego mamy kolejny typ wyliczeniowy (monadę) Result:

enum Result<T, E> {
  Ok(T),
  Err(E)
}

I dzięki pattern matchingowi mamy emulowany try {} catch() {}:

fn try(i: i32) -> Result<i32, String> {
  if i < 0 {
    Err("Less than 0")
  } else {
    Ok(i)
  }
}

let val = match try(10) {
  Ok(v) => v,
  Err(s) => {
    println!("{}", s);
    0
  }
};

assert_eq!(val, 10);

let val = match try(-10) {
  Ok(v) => v,
  Err(s) => {
    println!("{}", s);
    0
  }
};

assert_eq!(val, 0);

Pozostało 580 znaków

2015-01-28 10:35
0

Krótkie słowa kluczowe (no może nie aż tak krótkie) to nie nowość: let, var, def, dim - to już gdzieś tam było.
Dwu-literowe może same w sobie nie są trudne do zrozumienia, tylko raczej łatwe do przeoczenia.


Szacuje się, że w Polsce brakuje 50 tys. programistów

Pozostało 580 znaków

2015-01-28 16:45
0

@vpiotr w Ruscie IMHO nie ma z tym problemu, bo dwuliterowych słów kluczowych używa się praktycznie tylko w deklaracjach funkcji. W pozostałych przypadkach dobrą praktyką jest pomijanie typów tam gdzie mogą być rozpoznane przez kompilator, więc nie za często się spotyka te słowa.

Ktoś jeszcze wpadnie na pomysł enkodowania typów w nazwie zmiennej (bo kompilator wie, ale programista nie) i historia zatoczy koło... - Endrju 2015-01-28 18:24
Tu bardziej chodzi mi o HMTS jak w Haskellu. Typ zmiennej jest dedukowany w czasie kompilacji więc notacja węgierska nie ma najmniejszego sensu. - hauleth 2015-01-29 02:20

Pozostało 580 znaków

2015-01-28 17:34
2

Krótkie nazwy typów znacznie utrudniają stosowanie dwuznakowych nazw zmiennych.
Chyba już wiemy, komu ten język najbardziej się nie spodoba. ;)


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."
Co gorsza, nie ma preinkrementacji (postinkrementacji też zresztą). - msm 2015-01-28 17:55
Z drugiej strony if i match zwracają wartość, więc da się pominąć trochę zmiennych :P - hauleth 2015-01-28 17:58

Pozostało 580 znaków

2015-01-28 20:27
3

Rust ma jeden killer feature, którego nie ma nic innego: bezpieczeństwo pamięci bez GC. Natomiast jeśli chodzi o funkcyjnosc czy wygodę programowania, to raczej ze Scalą nie ma szans, ale to inne zastosowania
.

Pozostało 580 znaków

2015-01-28 22:27
0

Myślę, że będzie jak z każdym innym językiem, czyli będą narzędzia/frameworki/biblioteki to i znajdzie się ktoś kto będzie tego używał.

Mozilla pisze w nim Servo i powoli zaczynają przenosić kod z Servo do Gecko. - hauleth 2015-01-29 13:41

Pozostało 580 znaków

2015-01-28 22:45
0
winerfresh napisał(a):

Kolejną rzeczą, o której zapomniałem jest brak wyjątków. Zamiast tego mamy kolejny typ wyliczeniowy (monadę) Result:

enum Result<T, E> {
Ok(T),
Err(E)
}

I dzięki pattern matchingowi mamy emulowany try {} catch() {}:


fn try(i: i32) -> Result<i32, String> {
if i < 0 {
Err("Less than 0")
} else {
Ok(i)
}
}

let val = match try(10) {
Ok(v) => v,
Err(s) => {
println!("{}", s);
0
}
};

assert_eq!(val, 10);

let val = match try(-10) {
Ok(v) => v,
Err(s) => {
println!("{}", s);
0
}
};

assert_eq!(val, 0);



Skoro jest monada Result, to czy jest do tego jakieś do-notation? Co jeśli wywołam w jednej funkcji po kolei kilka funkcji, które mogą rzucać wyjątki i nie chcę tych wyjątków zignorować, a np obsłużyć gdzieś wyżej w hierarchii wywołań? Jak będzie wyglądał kod?

"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.

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