Форум программистов, компьютерный форум, киберфорум
Наши страницы
Lisp
Войти
Регистрация
Восстановить пароль
 
 
x33x
42 / 8 / 0
Регистрация: 27.01.2016
Сообщений: 9
#1

Почему Лисп не стал популярным языком программирования? - Lisp

10.05.2017, 10:01. Просмотров 5612. Ответов 199
Метки нет (Все метки)

Спасибо большое за помощь!

Как итог мне надо было написать макрос чтения, который из конструкции вида #[1 11] делал список (2 3 5 7 11), при этом если начальное или конечное значение во входных данных отрицательное, то должно выводиться nil.
Макрос вроде получился (во всяком случае проверки по значениям #[1 11]; #[-7 11]; #[1 -7] выдают то, что мне требовалось).

Ещё раз спасибо!

З.Ы. Интересный, конечно, язык Lisp. Только не понимаю почему он несильно популярный и мало известных продуктов на нём написано?
http://www.cyberforum.ru/lisp/thread2033014.html
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.05.2017, 10:01
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Почему Лисп не стал популярным языком программирования? (Lisp):

Firefox 3.5 стал самым популярным в мире
Браузер Firefox 3.5 от Mozilla впервые стал самым популярным в мире – он обошел...

Является ли html языком программирования?
Собственно вопрос в заголовке озвучен. Насколько я помню, когда меня учили...

Нужно определиться с языком программирования
Доброй ночи, друзья! Помогите, пожалуйста, определиться с выбором языка...

Нужно определиться с языком программирования
Доброй ночи, друзья! Помогите, пожалуйста, определиться с выбором языка...

Разве является Delphi языком программирования?
Когда учился, нам четко втемяшили, что Delphi это среда разработки,...

199
_sg
3704 / 3502 / 236
Регистрация: 12.05.2012
Сообщений: 2,437
18.05.2017, 10:02 #181
окружение erlang vs lisp:
https://trends.google.com/trends/explore?q=erlang,lisp

Добавлено через 1 минуту


Добавлено через 2 минуты
с 2004 г.:
https://trends.google.com/trends/explore?date=all&q=erlang,lisp

Добавлено через 15 минут
lisp, erlang vs c#
https://trends.google.com/trends/explore?date=all&q=erlang,lisp,c%23
2
Shamil1
Модератор
2068 / 1374 / 303
Регистрация: 26.03.2015
Сообщений: 5,002
18.05.2017, 10:20 #182
Цитата Сообщение от korvin_ Посмотреть сообщение
multiple-value-bind — это синтаксический сахар.
Значит, multiple-value-bind создаёт неявный список/вектор возвращаемых аргументов?
(а &optional и &rest - создают неявный список/вектор принимаемых аргументов?)

Цитата Сообщение от helter Посмотреть сообщение
Принимающая форма берёт столько значений, сколько заказывала, независимо от числа значений возвращающей формы.
multiple-value-call не заказывает определённое количество значений, а собирает все значения всех переданных ей форм
0
Shamil1
Модератор
2068 / 1374 / 303
Регистрация: 26.03.2015
Сообщений: 5,002
18.05.2017, 10:27 #183
Цитата Сообщение от _sg Посмотреть сообщение
окружение erlang vs lisp:
Я так понимаю, в выборку не попали запросы по scheme, racket, clojure (и elixir)
0
helter
Эксперт по математике/физике
3741 / 2769 / 297
Регистрация: 12.03.2013
Сообщений: 5,104
18.05.2017, 11:25 #184
Цитата Сообщение от Shamil1 Посмотреть сообщение
multiple-value-call не заказывает определённое количество значений, а собирает все значения всех переданных ей форм
На то он и специальный оператор, предназначенный конкретно для множественных значений.

Цитата Сообщение от Shamil1 Посмотреть сообщение
Значит, multiple-value-bind создаёт неявный список/вектор возвращаемых аргументов?
Вообще говорят, нет. В этом смысл — для множественных значений не надо ничего создавать.

Цитата Сообщение от Shamil1 Посмотреть сообщение
(а &optional и &rest - создают неявный список/вектор принимаемых аргументов?)
Не понял. &optional ничего не консит. Теоретически &rest консит, но если он игнорируется, зачем он будет консить?
0
Shamil1
Модератор
2068 / 1374 / 303
Регистрация: 26.03.2015
Сообщений: 5,002
19.05.2017, 14:16 #185
Цитата Сообщение от helter Посмотреть сообщение
Вообще говорят, нет. В этом смысл — для множественных значений не надо ничего создавать.
Компилятор должен выделить память под хранение возвращаемых значений. Так как он не знает, сколько значений будет возвращаться, то единственный? способ сделать это - выделить память под ссылку на структуру данных, которая во время исполнения будет содержать возвращаемые значения.

Добавлено через 15 секунд
Цитата Сообщение от helter Посмотреть сообщение
Вообще говорят, нет. В этом смысл — для множественных значений не надо ничего создавать.
Компилятор должен выделить память под хранение возвращаемых значений. Так как он не знает, сколько значений будет возвращаться, то единственный? способ сделать это - выделить память под ссылку на структуру данных, которая во время исполнения будет содержать возвращаемые значения.
0
helter
Эксперт по математике/физике
3741 / 2769 / 297
Регистрация: 12.03.2013
Сообщений: 5,104
19.05.2017, 14:52 #186
Цитата Сообщение от Shamil1 Посмотреть сообщение
Компилятор должен выделить память под хранение возвращаемых значений. Так как он не знает, сколько значений будет возвращаться, то единственный? способ сделать это - выделить память под ссылку на структуру данных, которая во время исполнения будет содержать возвращаемые значения.
По-моему, ему нужно знать, сколько значений будет приниматься, а не возвращаться. А это известно почти всегда. Впрочем, я уже говорил, что не знаю. Реализаций уже сейчас много, в дальнейшем могут появиться новые, везде внутренности могут быть разные.
0
budden
198 / 99 / 4
Регистрация: 16.08.2015
Сообщений: 193
19.05.2017, 20:56 #187
Цитата Сообщение от Shamil1 Посмотреть сообщение
Компилятор должен выделить память под хранение возвращаемых значений.
Я думаю, что это происходит через стек. Впрочем, на это есть disassemble, где можно посмотреть на генерируемый код.
0
XZnts
12 / 12 / 0
Регистрация: 15.02.2017
Сообщений: 19
22.05.2017, 11:54 #188
Если кому интересно поковыряться в ассемблере. Win64

Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
This is SBCL 1.3.15, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
 
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
 
WARNING: the Windows port is fragile, particularly for multithreaded
code.  Unfortunately, the development team currently lacks the time
and resources this platform demands.
* (defun f1 () (values 1 2))
 
F1
* (defun f2 () (let ((x (f1))) x))
 
F2
* (defun f3 () (multiple-value-bind (x y) (f1) (list x y)))
 
F3
* (disassemble 'f1)
 
; disassembly for F1
; Size: 48 bytes. Origin: #x10044D57E3
; 7E3:       498B4C2460       MOV RCX, [R12+96]               ; thread.binding-stack-pointer
                                                              ; no-arg-parsing entry point
; 7E8:       48894DF8         MOV [RBP-8], RCX
; 7EC:       84042500000F20   TEST AL, [#x200F0000]           ; safepoint
; 7F3:       BA02000000       MOV EDX, 2
; 7F8:       BF04000000       MOV EDI, 4
; 7FD:       488D5D10         LEA RBX, [RBP+16]
; 801:       B904000000       MOV ECX, 4
; 806:       BE17001020       MOV ESI, 537919511
; 80B:       F9               STC
; 80C:       488BE5           MOV RSP, RBP
; 80F:       5D               POP RBP
; 810:       C3               RET
; 811:       CC10             BREAK 16                        ; Invalid argument count trap
NIL
* (disassemble 'f2)
 
; disassembly for F2
; Size: 55 bytes. Origin: #x10044ECB63
; 63:       498B4C2460       MOV RCX, [R12+96]                ; thread.binding-stack-pointer
                                                              ; no-arg-parsing entry point
; 68:       48894DF8         MOV [RBP-8], RCX
; 6C:       84042500000F20   TEST AL, [#x200F0000]            ; safepoint
; 73:       488D5424F0       LEA RDX, [RSP-16]
; 78:       4883EC18         SUB RSP, 24
; 7C:       488B0595FFFFFF   MOV RAX, [RIP-107]               ; #<SB-KERNEL:FDEFN F1>
; 83:       31C9             XOR ECX, ECX
; 85:       48892A           MOV [RDX], RBP
; 88:       488BEA           MOV RBP, RDX
; 8B:       FF5009           CALL QWORD PTR [RAX+9]
; 8E:       480F42E3         CMOVB RSP, RBX
; 92:       488BE5           MOV RSP, RBP
; 95:       F8               CLC
; 96:       5D               POP RBP
; 97:       C3               RET
; 98:       CC10             BREAK 16                         ; Invalid argument count trap
NIL
* (disassemble 'f3)
 
; disassembly for F3
; Size: 139 bytes. Origin: #x1004558117
; 17:       498B4C2460       MOV RCX, [R12+96]                ; thread.binding-stack-pointer
                                                              ; no-arg-parsing entry point
; 1C:       48894DF8         MOV [RBP-8], RCX
; 20:       84042500000F20   TEST AL, [#x200F0000]            ; safepoint
; 27:       488D5424F0       LEA RDX, [RSP-16]
; 2C:       4883EC18         SUB RSP, 24
; 30:       488B0591FFFFFF   MOV RAX, [RIP-111]               ; #<SB-KERNEL:FDEFN F1>
; 37:       31C9             XOR ECX, ECX
; 39:       48892A           MOV [RDX], RBP
; 3C:       488BEA           MOV RBP, RDX
; 3F:       FF5009           CALL QWORD PTR [RAX+9]
; 42:       7208             JB L0
; 44:       BF17001020       MOV EDI, 537919511
; 49:       488BDC           MOV RBX, RSP
; 4C: L0:   488BE3           MOV RSP, RBX
; 4F:       488BDA           MOV RBX, RDX
; 52:       4D8B5C2418       MOV R11, [R12+24]                ; thread.alloc-region
; 57:       498D5320         LEA RDX, [R11+32]
; 5B:       493B542420       CMP RDX, [R12+32]
; 60:       7733             JNBE L2
; 62:       4989542418       MOV [R12+24], RDX                ; thread.alloc-region
; 67: L1:   498D5307         LEA RDX, [R11+7]
; 6B:       488BC2           MOV RAX, RDX
; 6E:       488958F9         MOV [RAX-7], RBX
; 72:       4883C010         ADD RAX, 16
; 76:       488940F1         MOV [RAX-15], RAX
; 7A:       488978F9         MOV [RAX-7], RDI
; 7E:       48C7400117001020 MOV QWORD PTR [RAX+1], 537919511
; 86:       84042500000F20   TEST AL, [#x200F0000]            ; safepoint
; 8D:       488BE5           MOV RSP, RBP
; 90:       F8               CLC
; 91:       5D               POP RBP
; 92:       C3               RET
; 93:       CC10             BREAK 16                         ; Invalid argument count trap
; 95: L2:   6A20             PUSH 32
; 97:       BA00002020       MOV EDX, #x20200000              ; alloc_tramp
; 9C:       FFD2             CALL RDX
; 9E:       415B             POP R11
; A0:       EBC5             JMP L1
NIL
Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
span class="sy0"> * (declaim (optimize (speed 3) (safety 0) (debug 0)))
 
NIL
* (defun f1 () (values 1 2))
WARNING: redefining COMMON-LISP-USER::F1 in DEFUN
 
F1
* (defun f2 () (let ((x (f1))) x))
WARNING: redefining COMMON-LISP-USER::F2 in DEFUN
 
F2
* (defun f3 () (multiple-value-bind (x y) (f1) (list x y)))
WARNING: redefining COMMON-LISP-USER::F3 in DEFUN
 
F3
* (disassemble 'f1)
 
; disassembly for F1
; Size: 37 bytes. Origin: #x10045C2E5E
; 5E:       84042500000F20   TEST AL, [#x200F0000]            ; safepoint
                                                              ; no-arg-parsing entry point
; 65:       BA02000000       MOV EDX, 2
; 6A:       BF04000000       MOV EDI, 4
; 6F:       488D5D10         LEA RBX, [RBP+16]
; 73:       B904000000       MOV ECX, 4
; 78:       BE17001020       MOV ESI, 537919511
; 7D:       F9               STC
; 7E:       488BE5           MOV RSP, RBP
; 81:       5D               POP RBP
; 82:       C3               RET
NIL
* (disassemble 'f2)
 
; disassembly for F2
; Size: 44 bytes. Origin: #x10045DA46E
; 6E:       84042500000F20   TEST AL, [#x200F0000]            ; safepoint
                                                              ; no-arg-parsing entry point
; 75:       488D5424F0       LEA RDX, [RSP-16]
; 7A:       4883EC18         SUB RSP, 24
; 7E:       488B05A3FFFFFF   MOV RAX, [RIP-93]                ; #<SB-KERNEL:FDEFN F1>
; 85:       31C9             XOR ECX, ECX
; 87:       48892A           MOV [RDX], RBP
; 8A:       488BEA           MOV RBP, RDX
; 8D:       FF5009           CALL QWORD PTR [RAX+9]
; 90:       480F42E3         CMOVB RSP, RBX
; 94:       488BE5           MOV RSP, RBP
; 97:       F8               CLC
; 98:       5D               POP RBP
; 99:       C3               RET
NIL
* (disassemble 'f3)
 
; disassembly for F3
; Size: 131 bytes. Origin: #x10046214EE
; 4EE:       84042500000F20   TEST AL, [#x200F0000]           ; safepoint
                                                              ; no-arg-parsing entry point
; 4F5:       488D5424F0       LEA RDX, [RSP-16]
; 4FA:       4883EC18         SUB RSP, 24
; 4FE:       488B05A3FFFFFF   MOV RAX, [RIP-93]               ; #<SB-KERNEL:FDEFN F1>
; 505:       31C9             XOR ECX, ECX
; 507:       48892A           MOV [RDX], RBP
; 50A:       488BEA           MOV RBP, RDX
; 50D:       FF5009           CALL QWORD PTR [RAX+9]
; 510:       7208             JB L0
; 512:       BF17001020       MOV EDI, 537919511
; 517:       488BDC           MOV RBX, RSP
; 51A: L0:   488BE3           MOV RSP, RBX
; 51D:       488BDA           MOV RBX, RDX
; 520:       4D8B5C2418       MOV R11, [R12+24]               ; thread.alloc-region
; 525:       498D4B20         LEA RCX, [R11+32]
; 529:       493B4C2420       CMP RCX, [R12+32]
; 52E:       7734             JNBE L2
; 530:       49894C2418       MOV [R12+24], RCX               ; thread.alloc-region
; 535: L1:   498D4B07         LEA RCX, [R11+7]
; 539:       488BC1           MOV RAX, RCX
; 53C:       488958F9         MOV [RAX-7], RBX
; 540:       4883C010         ADD RAX, 16
; 544:       488940F1         MOV [RAX-15], RAX
; 548:       488978F9         MOV [RAX-7], RDI
; 54C:       48C7400117001020 MOV QWORD PTR [RAX+1], 537919511
; 554:       84042500000F20   TEST AL, [#x200F0000]           ; safepoint
; 55B:       488BD1           MOV RDX, RCX
; 55E:       488BE5           MOV RSP, RBP
; 561:       F8               CLC
; 562:       5D               POP RBP
; 563:       C3               RET
; 564: L2:   6A20             PUSH 32
; 566:       B900002020       MOV ECX, #x20200000             ; alloc_tramp
; 56B:       FFD1             CALL RCX
; 56D:       415B             POP R11
; 56F:       EBC4             JMP L1
NIL
2
_sg
3704 / 3502 / 236
Регистрация: 12.05.2012
Сообщений: 2,437
24.05.2017, 08:52 #189
Emacs для начинающих
3
nullxdth
1268 / 478 / 44
Регистрация: 12.03.2013
Сообщений: 2,225
24.05.2017, 10:32 #190
Цитата Сообщение от XZnts Посмотреть сообщение
Если кому интересно поковыряться в ассемблере.
В данном случае не очень показательный код.
Для демонстрации того факта, что Lisp (как минимум, SBCL) генерирует одинаковый код, можно вот такой пример привести:
Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
(defun f1 ()
  (values 42 "foobar"))
 
(defun g1 ()
  (let ((x (f1)))
    x))
 
(defun f2 ()
  42)
 
(defun g2 ()
  (let ((x (f2)))
    x))
Как видно, g1 и g2 имеют идентичный код (отличаются только адреса).
В случае inline f1 и f2 - тоже самое.
Вывод: даже если функция имеет более чем одно возвращаемое значение, при использовании первого (основного) - мы не делаем ничего лишнего и, соответственно, не теряем в производительности.

Добавлено через 6 минут
Цитата Сообщение от Shamil1 Посмотреть сообщение
С точки зрения сабжа это ничего не меняет. Потенциальные лисперы не будут читать эту тему. Если есть желание изменить ситуацию (хотя бы в рамках данного форума), нужно эту и другую полезную для новичков информацию разместить в закреплённой теме.
Catstail, мне кажется Shamil1 прав. Если вы не против, может закрепим эту тему (несмотря на неблагозвучное название), а http://www.cyberforum.ru/lisp/thread962496.html открепим? От последней нет никакого толку. Когда у меня что-то потребное будет, я дам знать.

Добавлено через 8 минут
Цитата Сообщение от nullxdth Посмотреть сообщение
мы не делаем ничего лишнего и, соответственно, не теряем в производительности
Ну за тем исключением, конечно, что values всегда вычисляет все аргументы в соответствии с порядком.
2
vlisp
443 / 412 / 103
Регистрация: 10.08.2015
Сообщений: 1,394
Завершенные тесты: 1
24.05.2017, 10:35 #191
Цитата Сообщение от nullxdth Посмотреть сообщение
может закрепим эту тему (несмотря на неблагозвучное название), а Tcl/Tk via Common Lisp и LTK открепим?
еще чего не хватало...
0
nullxdth
1268 / 478 / 44
Регистрация: 12.03.2013
Сообщений: 2,225
24.05.2017, 10:41 #192
Цитата Сообщение от vlisp Посмотреть сообщение
еще чего не хватало...
Что вам не нравится? Закрепить эту тему или открепить http://www.cyberforum.ru/lisp/thread962496.html?
0
vlisp
443 / 412 / 103
Регистрация: 10.08.2015
Сообщений: 1,394
Завершенные тесты: 1
24.05.2017, 11:01 #193
Цитата Сообщение от nullxdth Посмотреть сообщение
Что вам не нравится?
Эта тема - бесполезная флудильня, та - тоже, но она хотя бы дает импульс к поиску материалов по GUI для лиспа
0
nullxdth
1268 / 478 / 44
Регистрация: 12.03.2013
Сообщений: 2,225
24.05.2017, 11:06 #194
Цитата Сообщение от vlisp Посмотреть сообщение
Эта тема - бесполезная флудильня
Не согласен. Тут много полезных сообщений.
Цитата Сообщение от vlisp Посмотреть сообщение
та - тоже, но она хотя бы дает импульс к поиску материалов по GUI для лиспа
Ну окей. Тут тоже можно оставить.
0
Shamil1
Модератор
2068 / 1374 / 303
Регистрация: 26.03.2015
Сообщений: 5,002
24.05.2017, 11:53 #195
Цитата Сообщение от nullxdth Посмотреть сообщение
может закрепим эту тему
По-моему, лучше создать новую. Чтобы не нужно было читать 10 страниц этой темы.

Нужна небольшая статья, отвечающая на следующие вопросы:

1. какой диалект выбрать
Краткая характеристика основных диалектов (видимо, это CL, Scheme и Clojure). На что ориентироваться при выборе диалекта.

2. какую иде выбрать
Краткая характеристика основных ИДЕ (под разные ОС - линукс/виндоуз/мак) для каждого из основных диалектов. Для "составных" ИДЕ - перечень используемого ПО и ссылки на учебники по ним.

3. с какого учебника начинать
Ссылки на учебники (tutorials) с кратким описанием. (Например, https://www.tutorialspoint.com/lisp/index.htm и https://www.tutorialspoint.com/clojure/index.htm ).
Список книг с кратким описанием и т.п.

4. где искать документацию по функциям
Желательно с примерами использования и "see also". Например, https://clojuredocs.org/clojure.core/sort .
0
Catstail
Модератор
23531 / 11641 / 2034
Регистрация: 12.02.2012
Сообщений: 18,979
24.05.2017, 13:59 #196
nullxdth, давайте так и сделаем. Эта тема закреплена. А тема ТCL/Tk тоже пусть пока побудет закрепленной.
0
vlisp
443 / 412 / 103
Регистрация: 10.08.2015
Сообщений: 1,394
Завершенные тесты: 1
25.05.2017, 08:49 #197
Цитата Сообщение от Shamil1 Посмотреть сообщение
где искать документацию по функциям
Начни с CLHS. Если дойдешь до середины и поймешь что не сошел с ума, перезвони.
0
helter
Эксперт по математике/физике
3741 / 2769 / 297
Регистрация: 12.03.2013
Сообщений: 5,104
25.05.2017, 13:25 #198
Цитата Сообщение от vlisp Посмотреть сообщение
Начни с CLHS. Если дойдешь до середины и поймешь что не сошел с ума, перезвони.
Вы когда слово в словаре ищете, начинаете читать словарь с начала? Ну-ну.
0
vlisp
443 / 412 / 103
Регистрация: 10.08.2015
Сообщений: 1,394
Завершенные тесты: 1
10.06.2018, 16:20 #199
Критика CL (en)
Из разряда must know.
0
antares0
238 / 107 / 8
Регистрация: 12.05.2015
Сообщений: 151
11.06.2018, 10:31 #200
Статья 84-го года?
В 90-ых указаное еще имело какой-то смысл. Но на сегодняшний день 2/3 из этого уже 2-а десятилетия неактуально. Оставшаяся треть личные и довольно спорные возрения автора при всех его регалиях. И за прошедшие годы это все не один раз воплощалось никак не повлияв на небольшую нишу CL.
Если кому интересна критика именно современного CL, то есть Common Lisp Recipes - A Problem-Solution Approach за авторством известного Edi Weitz. Уместной и гораздо более систематизированой критики и путевых заметок там более чем.
4
11.06.2018, 10:31
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.06.2018, 10:31
Привет! Вот еще темы с решениями:

Является ли Delphi современным алгоритмическим языком программирования?
Здравствуйте! Скажите пожалуйста, является ли Delphi современным...

Си является языком программирования низкого уровня или высокого?
у меня вопрос , си является низкий уровень или высокий уровень языка...

Почему Qt стал платным?
Привет. Только что посмотрел, появились платные версии Qt (хотя раньше вроде...

Почему я не стал фанатом Хаскел
Чуть было не стал. С подачи уважаемого _Ivana очень даже заинтересовался. Это...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
200
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru