Interesujące czy unikalne typy w językach programowania? [Zamknięte]

20

Wszyscy widzieliśmy liczbę całkowitą, zmiennoprzecinkową, łańcuch i okazjonalny typ dziesiętny. Jakie są najbardziej dziwne, unikalne lub przydatne typy, z którymi się spotkałeś, przydatne czy nie?

użytkownik10008
źródło
Witaj user10008, witaj w Programmers.SE! Czy sprawdziłeś nasze FAQ ? Które z sześciu subiektywnych wytycznych Twoim zdaniem spełnia twoje pytanie?
4
Czy ktoś chciałby napisać wpis dla Lisp?
Mark C
Myślałem, że to może być duplikat, ale tylko dlatego, że moja odpowiedź byłaby duplikatem, więc opublikuję link, a może znajdziesz kilka dobrych odpowiedzi: programmers.stackexchange.com/questions/724/…
Peter Turner
@Mark: Próbowałem, ale typy są prawdopodobnie jedną z najmniej interesujących rzeczy w Lisp.
Larry Coleman,
@ LarryC Myślałem, że to idealne pytanie dla Lisp z powodu wszechobecnego korzystania z list ! Listy tworzą drzewo składniowe, a to pozwala ci pisać funkcje, które robią niesamowite rzeczy w twoim kodzie, jak rozumiem. Uczę się teraz Racket (wcześniej PLT Scheme ). Lisp jest jedynym językiem programowania, w którym byłem naprawdę zmotywowany i zainteresowany nauką.
Mark C

Odpowiedzi:

18

Będę krótki:

Maybe a

w Haskell.

Dzięki tej prostej konstrukcji język rozwiązuje problem awarii lub NullPointerExceptionzgrabnie omija „One Million Mistake” Tony'ego Hoare'a :)

Szczerze mówiąc, opcjonalna obecność sprawdzana w czasie kompilacji? To marzenie ...

Matthieu M.
źródło
1
Lub Opcja, jak to się nazywa w wielu innych językach programowania.
Jonas
@Jonas: Muszę przyznać, że nie podoba mi się to Optionimię. Dlaczego nie Optional! Może dlatego, że nie jestem native speakerem, ale Optionnie przekazuje mi „opcjonalnego” znaczenia.
Matthieu M.,
MaybeNazwa jest słodkie: „Co masz?” „Może int”. Jednak naprawdę schludne jest to, że jest to zarówno funktor, jak i monada, co, mówiąc prosto, oznacza, że ​​otrzymujesz zerową propagację za darmo. Nigdy nie musisz umieszczać kontroli zerowej w funkcjach lub w środku kodu; wystarczy, że w ogóle to sprawdzisz na samym końcu kodu.
Tikhon Jelvis
15

Od zawsze lubię void *. Prawdopodobnie jest to objaw czegoś głęboko we mnie wadliwego.

Paul Nathan
źródło
2
Tak. Obawiam się, że to dokładnie to. :) Och, +1 za „interesujące” zamiast „niepowtarzalne”. Cel C ma oczywiście void *i Pascal / Delphi Pointer.
Frank Shearar,
haha bardziej nietypowy, ale nie można argumentować, że nie jest potężny
user10008
15
Uwielbiam nieodłączny pesymizm, który wyraża: „Widzisz tam tę rzecz?” „Tak, co to jest?”, „Nie mam pojęcia”.
biziclop,
Zawsze myślałem, że to zabawne, że nie możesz ogłosić pustki, ale możesz wziąć adres. Wydaje mi się, że z struct s {int A; nieważne B; int C; }, że adres B powinien być adresem pęknięcia między A i C. Ale nie, niedozwolone.
Andy Canfield
Dlatego w pascalu „wskaźnik” jest używany do oznaczenia ogólnego wskaźnika i nie myli się z „procedurą”.
umlcat
14

Lua ma wbudowany stół, który robi największe wrażenie. Ma wbudowany hashtable i wektor, a przy użyciu metatablów może być podstawową podstawą programowania obiektowego w języku proceduralnym.

Każdy indeks tabeli może odbierać dowolną z podstawowych struktur językowych (liczba, wartość logiczna, ciąg, funkcja-tak, funkcje są typami w lua - i tabele).

Machado
źródło
Zauważ, jak JavaScript jest zbudowany w bardzo podobny sposób, a Python jest zbudowany na tym samym fundamencie, podobnie jak prawdopodobnie Ruby.
9000
Myślę, że jest to również możliwe w Perlu i PHP, tak?
FrustratedWithFormsDesigner
Istnieje różnica między tabelami w lua a kontenerami mieszania w innych językach. Istnieje niewielka różnica w implementacji w sposobie, w jaki lua dystrybuuje wartości skrótu, co sprawia, że ​​jego tabele działają w sposób prawie magiczny. Przeważnie programuję w Pythonie i czasami okazuje się, że używam założeń, które się nie utrzymują, na podstawie moich oczekiwań dotyczących sposobu działania tabel w lua. Specyficznym przykładem tej magii jest to, że liczby całkowite mają wartość + 1. Oznacza to, że klucze liczb całkowitych są gęsto upakowane, a wartości +0,0 i -0,0 mają taki sam skrót (są równe)
SingleNegationElimination
9

Dziwię się, że nikt jeszcze nie wspomniał o Monadach ani Algebraicznych Typach Danych.

Jason Baker
źródło
Może pokaż nam przykłady :)
nawfal
8

Lisp ma dwa ciekawe typy: ti nil. Interesujące w nich jest to, że wszystko jest ti nic nie jestnil .

Larry Coleman
źródło
Mówisz poważnie? Nie wiedziałem tego.
Mark C
Czy ? nilt
Jon Harrop
6

SNOBOL: wzorzec (zasadniczo drzewo analizatora składni LL (1), jeśli dobrze go pamiętam).

David Thornley
źródło
6

Fortran ma wspólne bloki; jest to jeden z najmniej popularnych typów danych we współczesnych językach lub raczej nietypowy sposób efektywnego udostępniania danych.

Fortran 95 ma typy interwałów i wbudowaną arytmetykę interwałów.

Lista nie byłaby kompletna bez typów monadycznych znalezionych w Haskell. Aby je zrozumieć, potrzebujesz trochę wysiłku.

9000
źródło
Ach, bazy danych UniData / UniVerse mają również wspólne bloki w swoim języku wewnętrznym (UniBasic).
Dan McGrath
Czy wspólny blok to blok kodu używany przez różne części programu?
Mark C
1
@ MarkC IIRC to zasadniczo dane globalne, ale każda funkcja, do której uzyskuje się dostęp, musi wyraźnie powiedzieć, że będzie na górze
jk.
5

Delphi ma zestawy ( patrz także ), które, jak sądzę, nie są implementowane w ten sam sposób w innych językach.

To sprawia, że ​​przechowywanie atrybutów o wielu zmiennych w bazach danych jest dziecinnie proste: D

Peter Turner
źródło
4

Przypuszczam, że to naprawdę dziwne, że pochodzi z programowania na klasycznej architekturze, ale z pewnością jednym z najtrudniejszych rodzajów, dla których na początku zawinąłem głowę, był rejestr kwantowy , który pojawia się w QCL .

Cercerilla
źródło
3

PL / SQL pozwala zadeklarować zmienne typu my_table.some_column%type... Uważam, że to cholernie przydatne.

A C # pozwala zadeklarować obiekty jako zerowalne lub nie, chociaż nie jestem pewien, czy liczy się to jako typ.

FrustratedWithFormsDesigner
źródło
4
Ale cursor%rowtypejest jeszcze zabawniejszy: jest to dynamicznie formowany typ rekordu, który odzwierciedla, które kolumny zwraca zapytanie kursora.
9000
.NET „Nullable” jest w rzeczywistości (ogólnym) typem samym w sobie.
Konamiman
3

Miałem słabość w sercu Euphoria typów danych „s, kiedy byłem młodszy

Ma następującą strukturę:

Object
-> Atom
-> Sequence
  • Atom = Pojedyncza wartość liczbowa
  • Sekwencja = Sekwencja obiektów

    -- examples of atoms:
    
    0
    98.6
    -1e6
    
    -- examples of sequences:
    
    {2, 3, 5, 7, 11, 13, 17, 19}
    {1, 2, {3, 3, 3}, 4, {5, {6}}}
    {{"jon", "smith"}, 52389, 97.25}
    {}                        -- the 0-element sequence
    

    Zobacz: Podręcznik referencyjny

Uwaga: „jon” jest w rzeczywistości krótkim sposobem na napisanie sekwencji wartości ASCII. Na przykład "ABCDEFG"jest taki sam jak{65, 66, 67, 68, 69, 70, 71}

Dan McGrath
źródło
7
To czuje się jak LISP ...
FrustratedWithFormsDesigner
Rzeczywiste typy danych są jedynym bitem.
Dan McGrath
1
@FrustratedWithForms Same, pomyślałem: „Hej, powiedział:„ Atom ”! To wygląda jak (a) Lisp, ale z niepotrzebnymi dzielnikami.: P
Mark C
3

Felix ma anonimowe typy sum. Typ jest zapisany w następujący sposób:

typedef il = int + long;

jak byłoby w teorii. Wartości są brzydkie:

case 0 of il (1)
case 1 of il (2L)

z wyjątkiem być może sumy jednostkowej, takiej jak 3 = 1 + 1 + 1

case 0 of 3
case 1 of 3 

który niestety wykorzystuje zerowe liczenie początku dla „zgodności C”. Anonimowe sumy są niezbędne dla strukturalnie typowanych typów algebraicznych, na przykład:

(1 + T * li) as li

jest (pojedynczo połączoną) listą T. Wszystkie inne języki, jakie znam, o wymaganych nominalnie wpisanych sumach, przy czym zarówno sam typ, jak i konstruktory muszą mieć nazwy.

Skrót 3 użyty powyżej jest uroczy, w bibliotece znajduje się:

typedef void = 0;
typedef unit = 1;
typedef bool = 2;

i ta notacja:

 T ^ 3

jest tablicą o długości statycznej 3 .. 3 nie jest liczbą całkowitą, ale sumą 3 jednostek. Jaka szkoda + nie kojarzy się :)

Yttrill
źródło
2

q / kdb + ma wbudowane tabele. Ponieważ jest to język programowania i zorientowana na kolumny baza danych w jednym, nie ma potrzeby korzystania z LINQ ani ORM.

Na przykład można utworzyć tabelę podobną do tej (przypisanie wyróżnia się :raczej niż =w większości języków):

people:([]name:`Joe`Amy`Sarah; age:17 15 18; GPA:3.5 3.8 3.33)

Teraz mogę spojrzeć na mój stół:

q)show people
name  age GPA 
--------------
Joe   17  3.5 
Amy   15  3.8 
Sarah 18  3.33

I mogę zapytać:

q)select from people where GPA>3.4
name age GPA
------------
Joe  17  3.5
Amy  15  3.8
chrisaycock
źródło
2

Kiedy po raz pierwszy o nich usłyszałem, związek w C ++ był „dziwaczny”. Nadal nie natrafiłem na scenariusz, w którym są oczywistym wyborem do wdrożenia.

Mumia
źródło
3
Związki pochodzą z C. Dobrym przykładem jest struktura zval w php.
Martin Wickman,
2
Użyłem ich w emulatorze Z80, aby łatwo uzyskać dostęp do rejestrów 16-bitowych jako całych rejestrów (HL, BC) i jako rejestrów 8-bitowych (H, L, B i C). To odzwierciedla ich użycie w Z80 asm. Również w „warianty”, klasę, która może pomieścić wartości różnych typów (na przykład int / float) - nie wiem, dlaczego nie korzystać podklasy, ale to miało sens w momencie :)
ggambett
@ggambett: Zrobiłem dokładnie to samo dla moich programów Z80! Tyle tylko, że dodałem również pole bitowe, aby uzyskać dostęp do poszczególnych flag w rejestrze F.
Konamiman
2

Wciąż próbuję zawinąć głowę wokół tego, czym staje się funkcja wieloparametrowa w języku F # i innych językach funkcjonalnych. Zasadniczo int f (Foo, Bar) staje się func f (Foo)

Jest to funkcja dwuparametrowa, która pobiera Foo, a Bar i zwraca int jest tak naprawdę funkcją jednoparametrową, która pobiera Foo i zwraca funkcję jednego parametru, która bierze pręt i zwraca int. Ale jakoś możesz to nazwać za pomocą dwóch parametrów, jeśli chcesz. Tutaj napisałem o tym post

Michael Brown
źródło
8
Raczej funkcja f(Foo, Bar)jest taka sama jak funkcja, f(Foo)która zwraca inną funkcję, f'(Bar)która zwraca wartość, która f(Foo, Bar)by zwróciła. Oznacza to, że jeśli naprawisz argument „Foo”, ale nie „Bar”, masz funkcję, która nie zależy od „Foo”, ale nadal zależy od argumentu „Bar”. Jest to typowe dla języków funkcjonalnych; nazywa się to „curry”.
9000
2

Wyrażenia regularne:

Są niezwykle potężnymi, ale kompaktowymi obiektami.
Języki, w których są wbudowane, mają dużą zdolność do manipulowania tekstem (nie słychać parsowania słowa, że ​​nie są tak dobre).

Martin York
źródło
2
Całkiem możliwe jest parsowanie wielu prostych gramatyk za pomocą wyrażeń regularnych. Na przykład stosunkowo proste jest parsowanie pliku ini przy minimalnej logice nad zestawem wyrażeń regularnych. Błędem wielu ludzi jest próbowanie z nim parsować bardzo złożone gramatyki (np. XML / HTML).
Matthew Scharley,
@Mark C: Na górze jest odpowiedź (rekord pobił 4320 głosów). Nie możesz
Martin York,
Tak, to było z humoru. Przyszło mi do głowy, gdy czytam komentarz Matthew.
Mark C
2

Kilka języków w rodzinie funkcjonalnej ma klasę typów znanych jako Jedność. Cechą wyróżniającą typy Unity jest to, że nie zawierają żadnych informacji, są to typy zero-bitowe. Typ jedności (w niektórych odmianach) jest również jego jedyną wartością lub (w większości innych) ma tylko jedną wartość (która sama nie jest typem).

Są one jednak przydatne, ponieważ są to typy wyróżnione. Ponieważ nie można niejawnie konwertować z jednego typu jedności na inny, można sprawić, że sprawdzanie typu statycznego będzie działać w bardzo wydajny i ekspresyjny sposób.

Jedność jest także sposobem, w jaki większość takich języków opisuje Enums, pozwalając, aby nowy typ był dowolnym zdefiniowanym zestawem innych typów, lub opisywać może typy, które mogą być albo wartością typowego typu (powiedzmy liczbą całkowitą) lub mieć wartość reprezentującą brak wartości.

Niektóre języki, które nie wykorzystują bogactwa typów jedności zdefiniowanych przez użytkownika, nadal mają w sobie jedność, w takiej czy innej formie. Na przykład, Python ma co najmniej trzy rodzaje jedności NoneType, NotImplementedTypeorazEllipsisType . Interesujące jest to, że pierwsze dwa oba oznaczają coś w rodzaju „Brak wartości”, ale trzecia jest używana w wartościach złożonych (w szczególności wyrażeniach plasterków) w celu przedstawienia interesujących przypadków specjalnych.

Inne ciekawe przykłady jedności obejmują NULLw SQL i undefinedjavascript, ale nie voidw C lub C ++. voidzawodzi. Mimo że opisuje wartość braku informacji, ale żadna rzeczywista wartość nie może być typu void.

SingleNegationElimination
źródło
Myślę, że masz na myśli „typ jednostki”.
Jason Baker,
2

symbolTyp Ruby jest nieco niezwykły. Jest to zasadniczo ciąg implementujący wzorzec singletonu. Lub coś. Jak dotąd znalazłem najlepsze zastosowanie symboli w stanach śledzenia i przekazywaniu nazw funkcji.

filozofodad
źródło
Również jako klucze do mapy do porównania kluczy O (1).
Jeremy Heiler
Cóż, to nie jest tak niezwykłe. Ruby odziedziczyła go po Smalltalk, który odziedziczył go po Lispie. Scala też to ma, tak myślę. W rzeczywistości prawie każda implementacja języka (kompilator lub interpreter) ma wewnętrznie tablicę symboli, Lisp, Smalltalk i Ruby po prostu udostępniają ją programiście.
Jörg W Mittag,
1

COBOL. Zasadniczo tylko dwa podstawowe typy danych, ciągi i liczby, ale musisz dokładnie określić , jak są ułożone w pamięci, np PIC S9(5)V99 COMP-3.

dan04
źródło
Mogę to pokonać. BCPL ma jeden typ danych - słowo; patrz en.wikipedia.org/wiki/BCPL
Stephen C
Istnieją różne typy liczb (COMP, COMP-1, COMP-2, COMP-3).
David Thornley,
To brzmi okropnie. Czy możesz wyjaśnić, co oznaczają te szczegóły?
Mark C
S= podpisany, 9(5)= 5 cyfr, V= domyślny przecinek dziesiętny, 99= 2 dodatkowe cyfry, COMP-3= BCD + znak nybble.
dan04
1

Clipper miał „Bloki kodu”, które były podobne do metod anonimowych. Można je przekazywać i oceniać w razie potrzeby, zwykle jako formę oddzwaniania. Często używasz ich do wykonywania obliczeń w locie podczas prezentacji tabel danych.

Grandmaster B.
źródło
0

VHDL ma typy fizyczne. Literał tego typu zawiera zarówno wartość, jak i jednostkę. Możesz również zdefiniować podjednostki. Na przykład predefiniowanym typem fizycznym jest time:

type time is range <machine dependant> to <machine dependant> 
units
  fs;
  ps = 1000 fs;
  ns = 1000 ps;
  us = 1000 ns;
  Ms = 1000 us;
  sec = 1000 ms;
  min = 60 sec;
  hr = 60 min;
end units;

Wraz z przeciążeniem operatora możesz zdefiniować bardzo interesujące rzeczy.

mouviciel
źródło
0

Clojure jest interesujący, ponieważ ma meta-koncepcję „abstrakcji”, która przenika język. Przykłady:

  • Kolekcje
  • Sekwencje (leniwe i nie leniwe)
  • Funkcje wyższego rzędu
  • Multimetody
  • Protokoły
  • Zarządzane referencje
  • Makra
  • różne inne .....

W pewnym stopniu abstrakcje doprowadzają do skrajności „ zasadę pojedynczej odpowiedzialności ”. To Ty musisz je skomponować, aby uzyskać pożądaną funkcjonalność, ale możesz być bardzo elastyczny w kwestii tego, jak je sklejasz.

Na przykład, jeśli chcesz oparty na klasach system OOP z dziedziczeniem, możesz stosunkowo szybko zbudować jeden z tych podstawowych abstrakcji.

W praktyce same abstrakcje są zaprojektowane w taki sposób, że możliwe są liczne implementacje, np. Poprzez określone interfejsy, takie jak clojure.lang.ISeq dla sekwencji lub clojure.lang.IFn dla funkcji wyższego rzędu.

Jest ciekawy film na ten temat: The Art of Abstraction

mikera
źródło
0

Jeśli chcesz mieć język unikalnego typu, wybierz BCPL . Ten język ma tylko jeden typ danych, słowo, będące stałą liczbą bitów dla implementacji języka.

uɐɪ
źródło
0

Googles Go ma unikalny typ „kanału”.

Brainlag
źródło
1
Kanały nie są wyjątkowe. Wiele języków je ma. Felix miał je 10 lat przed istnieniem Google'a :) Ocaml miał je 10 lat przed istnieniem Felixa.
Yttrill
I istniał przynajmniej jeden inny język, który miał kanały zanim istniał Ocaml. Nadal jeden z najmniej dostępnych typów w językach programowania.
Brainlag