В этой статье я расскажу о том, как можно в языке программирования SPL решить классическую задачу: получить список наиболее часто встречающихся в тексте слов. В качестве образца текста возьмем произведение Шекспира Гамлет.

Далее я сразу приведу пример программы и результат ее работы, а потом подробно разберем все шаг за шагом.

Текст программы:

text = #.readtext("hamlet.txt")
words = #.split(text, " ", ".", ",", ";", "'", "!", "?", "-", "(", ")", "[", "]", #.crlf, #.quot)
> i, 1..#.size(words)
  >> words[i] = ""
  key = #.lower(words[i])
  dict[key] += 1
  total += 1
<
#.sortval(dict)
#.reverse(dict)
#.output(total, " слов; ", #.size(dict), " уникальных слов")
> i, 1..10
  key = dict[i]
  #.output(i, " : ", key, " = ", dict[key])
<

Результат работы программы:

32885 слов; 4634 уникальных слов
1 : the = 1091
2 : and = 969
3 : to = 767
4 : of = 675
5 : i = 633
6 : a = 571
7 : you = 558
8 : my = 520
9 : in = 451
10 : it = 421

Теперь разберем подробнее как это работает.

Первая строка:

text = #.readtext("hamlet.txt")

считывает текст файла «hamlet.txt» в переменную «text».

Затем в строке:

words = #.split(text, " ", ".", ",", ";", "'", "!", "?", "-", "(", ")", "[", "]", #.crlf, #.quot)

функция "#.split" делит текст «text» на отдельные слова с помощью указанных разделителей и сохраняет результат в массив «words». В списке разделителей также присутствуют системные константы "#.crlf" и "#.quot", которые обозначают символы CRLF (перевод строки) и кавычки ".

Далее идет цикл, который начинается командой ">". В первой строке цикла:

> i, 1..#.size(words)

указано, что циклить он будет по переменной «i», которая меняется от 1 до количества слов в массиве «words», которое возвращает функция "#.size".

В следующей строке:

>> words[i] = ""

стоит команда перехода на начало цикла ">>" при условии, что очередное слово «words[i]» — не пустое. Это для того, чтобы не учитывать пустые слова, которые получились при делении текста.

Затем в текстовой переменной «key» получаем очередное слово в нижнем регистре благодаря функции "#.lower":

key = #.lower(words[i])

и следующая строка:

dict[key] += 1

выполняет основную работу — в запись из словаря «dict» по ключу «key» прибавляется 1, таким образом подсчитывая количество каждого слова.

В строке:

total += 1

подсчитывается общее количество слов, которые были учтены, и результат хранится в переменной «total».

Следующая строка:

<

это конец цикла.

Теперь сортируем словарь «dict» по значению:

#.sortval(dict)

Сортировка производится в порядке возрастания, поэтому в следующей строке:

#.reverse(dict)

словарь реверсируется в обратный порядок, по убыванию.

В принципе, работа сделана, нужно напечатать результат. Следующая строка выдает немного статистики:

#.output(total, " слов; ", #.size(dict), " уникальных слов")

где размер словаря «dict», возвращаемый функцией "#.size", дает нам количество уникальных слов.

Следующий цикл:

> i, 1..10

выводит 10 наиболее часто употребляемых слов.

Эта строка:

key = dict[i]

получает очередной ключ словаря, который и есть слово,

а следующая строка:

#.output(i, " : ", key, " = ", dict[key])

печатает и это слово, и сколько раз оно встречается в тексте. Таким образом, обращение к словарю по числовому индексу возвращает нам ключ записи с этим порядковым индексом, а обращение к словарю по текстовому ключу возвращает нам значение записи, которым является число — сколько раз это слово встретилось в тексте.

Последняя команда:

<

закрывает цикл.

Как видно из этого примера, SPL полностью автоматически определяет тип всех объектов — числовых и текстовых переменных, массивов, а также других объектов. При работе со словарем добавление новых записей производится автоматически.

Спасибо за внимание и успехов в программировании!
Поделиться с друзьями
-->

Комментарии (72)


  1. AStek
    11.06.2017 15:06
    +2

    Пример это отлично, вот только я об этом языке первый раз услышал. Ты бы хоть ссылку вставил на описание.


  1. Merlen_Gross
    11.06.2017 15:06
    +2

    Пользы от статьи мало. Обычно, языки программирования решают множество задач. Причём, одни подходят лучше для определённых типов задач, а другие — хуже. Так что, в итоге, автор говорит: "Есть язык, он работает — дальше ищите сами".


  1. Mr_Kibernetik
    11.06.2017 15:38
    -1

    Спасибо за публикацию статьи и комментарии!

    Очень сложно в одной статье описать целый язык. Даже если вкратце пробежаться по синтаксису, возможностям и особенностям, то получится очень большой текст, фактически — перепечатка документации по языку. Вряд ли подобные портянки представляют большой интерес.

    Поэтому я решил познакомить читателей с языком SPL не на теоретическом материале, а разобрав небольшой конкретный пример. Это и достаточно сжато, и при этом вполне информативно, чтобы понять, с чем имеем дело.

    Если читателям интересно, я могу в серии публикаций подробно раскрыть тему и осветить различные особенности и возможности языка SPL, затронув и особенности синтаксиса, и особенности практического применения.

    Нужно отметить, что язык SPL сейчас находится в стадии активного развития. И основное его назначение — быть полезным в области повседневного программирования. Это — язык для хобби, для обучения программированию, для того, чтобы любитель сразу получил результат без необходимости предварительного длительного изучения языка и различных API.

    Ссылка на подробное описание языка SPL: http://kibernetik.pro/blog/


    1. RPG18
      11.06.2017 16:07
      +1

      быть полезным в области повседневного программирования

      Тут нужно пояснение, что такое область повседневного программирования. Т.к. лично для меня, область повседневного программирования- это разработка сервисов(микросервисов). Соответственно приходится работать с PostgreSQL, Elasticsearch, JSON и т.д.


    1. mwizard
      11.06.2017 18:40

      Спасибо за публикацию статьи

      А вы не обделены скромностью.


      1. Mr_Kibernetik
        11.06.2017 18:57
        +2

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


        1. mwizard
          11.06.2017 18:59

          Пардон, я не увидел флажок "из песочницы". Приношу извинения, я был не прав.


    1. bormotov
      12.06.2017 01:18
      +1

      Очень сложно в одной статье описать целый язык. Даже если вкратце пробежаться по синтаксису, возможностям и особенностям, то получится очень большой текст, фактически — перепечатка документации по языку.


      Познакомьтесь со статьями на википедии про Lisp, Smalltalk, Scheme, Python, Ruby… Список можно продолжать, пока языки не закончатся… APL, K. J…

      Ни одна из этих статей не являются документацией по языку, но дают хорошее представление (и не только)


      1. Crandel
        12.06.2017 11:25

        Или вот тоже хороший ресурс, в котором кратко описано множество языков программирования(сабж отсутствует, кстати)


        1. grossws
          12.06.2017 16:02

          Исходя из того, что подробное описание находится на сайте автора, то это с большой вероятностью его собственное творение. У меня с spl ассоциируется эзотерический Shakespeare programming language.


          1. Mr_Kibernetik
            12.06.2017 16:32

            Вы правы, SPL — это мое собственное творение.


  1. alexkunin
    11.06.2017 15:52
    +3

    Имя немножко перегружено:

    SPL — The SPL Programming Language
    Shakespeare Programming Language (SPL)
    Streams Processing Language (SPL)
    Search Processing Language
    SPL (Simple Programming Language)
    Systems Programming Language, SPL
    Samsung Printer Language (SPL)

    Дальше я устал линковать, и это были только языки — есть же еще Standard PHP Library, и т.д.

    В общем, название слегка занято. Очевидные проблемы с гуглежом.


    1. Mr_Kibernetik
      11.06.2017 16:27

      Да, вы правы. Но, например, тут Wikipedia эта аббревиатура свободна.


      1. alexkunin
        11.06.2017 16:32

        Это еще раз доказывает, что Википедия не может быть самостоятельным надежным источником информации.

        Впрочем, там сверху так и написано:

        The aim of this list of programming languages is to include all notable programming languages in existence, both those in current use and historical ones, in alphabetical order, except for dialects of BASIC, esoteric programming languages, and markup languages.
        Т.е. малозначительные и эзотерические (например, Shakespeare Programming Language) языки там не упоминаются.


        1. dartraiden
          12.06.2017 00:39

          Как и в рувики, в общем.

          Список в Википедии это не «список вообще всего, что существует». Это список того, что рассматривается в авторитетных источниках. Причём, если не ошибаюсь, требуется рассмотрение в совокупности.


  1. Akdmeh
    11.06.2017 16:03
    +1

    Эту задачу можно решить почти на любом языке. Какие области применения, чем он лучше существующих аналогов, да хотя бы того же Python?


    1. Mr_Kibernetik
      11.06.2017 16:21

      Любую задачу можно решить почти на любом языке. Если вы хотите сравнения, то пожалуйста: пример кода на SPL приведен. Вы можете составить код аналогичной программы на другом языке, который вы знаете и считаете подходящим. У вас получится написать более простой код? Будет ли ваш код так же прост и понятен новичку в программировании? Вот мы и посмотрим, лучше ли SPL существующих аналогов или нет.


      1. mwizard
        11.06.2017 18:43

        Код на любом языке программирования, включая ассемблер и APL, будет проще и понятнее, чем "SPL".


        1. petropavel
          11.06.2017 19:09

          Ну это вы зря. За исключением ">>" все в примере вполне прозрачно, так что даже было непонятно, зачем там строчку за строчкой все разжевывать. По понятности и компактности он явно даст фору многим языкам, не только ассемблеру.

          Но не всем, есть и другие легко читаемые и компактные языки, так что тема не раскрыта — кому и нафига этот SPL нужен?


          1. Mr_Kibernetik
            11.06.2017 19:17

            Назначение SPL — язык для любителей программировать в качестве хобби. Максимально просто и эффективно решать повседневные задачи, учиться программировать.


      1. gudvinr
        11.06.2017 19:08
        +1

        Как минимум, реализация циклов не особо интуитивна «для новичка».
        Неясно, почему пространство стандартных функция выражается через `#.*` (это, скорее, просто условное «соглашение», но в большинстве языков это даёт основание полагать, что `#` — это объект, но при этом, судя по коду, объектов в языке нет).
        Неявное создание переменных (dict при итерации цикла) — тоже не самая понятная вещь.

        Сходу можно привести такую наивную реализацию на питоне:

        import re
        from urllib.request import urlopen
        
        with urlopen('http://erdani.com/tdpl/hamlet.txt') as r:
            text = r.read().decode()
        
        words = re.split('\W', text)
        words = filter(None, words)
        words = [s.upper() for s in words]
        
        freq = dict()
        for s in words:
            freq[s] = freq[s] + 1 if s in d else 1
        
        top = sorted(freq.items(), key=lambda x: x[1], reverse=True)
        
        for i in range(10):
        	print('{}: {} = {}'.format(i, *top[i]))
        


        Кроме того, в стандартной библиотеке для этого уже даже реализован метод и получение словаря можно уложить в пару строк (не в угоду читабельности, конечно):
        from collections import Counter
        
        words = [s.upper() for s in filter(None, re.split('\W', text))]
        Counter(words).most_common()
        


        Возможно, не совсем честно использовать regex, поэтому можно сделать разделение лишь средствами языка, например, так:
        sep = '''
        .,;!?-()'"[]
        '''.strip()
        words = ''.join([s if s not in sep else ' ' for s in text]).split()
        


        1. Mr_Kibernetik
          11.06.2017 19:26

          Спасибо за пример на Питоне. Вот и хорошая возможность сравнить два языка — сколько функций используется, насколько читаем и понятен код.
          В SPL "#" является системной группой, которой принадлежат все библиотечные функции. Это сделано для того, чтобы разделить пространство имен функций пользователя и системных функций.


          1. gudvinr
            11.06.2017 21:37
            +1

            Но сравнивать язык по конкретному примеру довольно некорректно. Я, например, не вижу реализации модулей, а без них единственное представление программы — это сплошная простыня текста. Не говоря уже о написании библиотек.


            К тому же, вы утверждаете, что в языке нет ключевых слов, что далеко не так. "Слова" в вашем случае — это просто неочевидные закорючки вместо латиницы. Это сложно назвать преимуществом, потому что для новичка помимо того, чтобы разбираться, с, собственно, программированием как таковым, придётся ещё и в справку по языку постоянно лезть.


            Я считаю, что синтаксис далёк от лаконичного и лично у меня вызывает странные ощущения.


            > i, 1..10
              ? i%2 = 0
                #.output(i)
              .
            <

            как минимум, точка — не самый лучший терминатор, потому что её банально можно не увидеть. И соотносить начало и конец блока визуально неудобно.


            Если сделать тоже самое на питоне (да и на любых других популярных языках), то происходящее легко поймёт человек, вообще не знакомый с программированием.


            for i in range(1,10):
                if i%2 == 0:
                    print(i)


            1. Mr_Kibernetik
              11.06.2017 21:55

              «Закорючки» — это не слова. Точно такие же закорючки есть и в Питоне. Но помимо закорючек в Питоне есть еще и обязательные английские слова, а SPL ограничивается только закорючками.
              Если вы приводите пример лаконичности, то вместо частного случая было бы интересно посмотреть на две команды внутри FOR и две команды внутри IF. Подозреваю, что код сразу распухнет из-за необходимости добавить так вами нелюбимые закорючки, а в SPL — нет.


              1. Levhav
                12.06.2017 03:17

                На пример вот. Выглядит почти так же.

                for i in range(1,100):
                    if i%2 == 0:
                        print(i)
                        print(i%11)
                
                    if i%3 == 0:
                        print(i)
                        print(i%7)
                
                


                Вам так много вопросов задают зачем этот язык нужен чтоб понять для себя надо ли тратить время на его изучение и какие от этого выгоды можно получить.

                Так как учить всё подряд не возможно, я предпочитаю изучать только наиболее перспективные технологии. А здесь пока не ясно в каких ситуациях знание SPL даст какие то преимущества.


                1. Mr_Kibernetik
                  12.06.2017 04:10

                  Знаете, вопросы относительно нужности SPL изначально ставятся в неверной плоскости. Я бы сказал даже так: если вы — программист, то SPL вам не нужен. Он вам нужен, если вы — не программист. Если вы — просто человек, которому интересно попробовать программирование. Студент не программистской специальности, домохозяйка, любопытный ребенок. Все дело в том, что современные языки программирования поставили стену между такими вот «случайными» людьми и программированием. В то время как нас просто окружают компьютеры, а программирование само по себе может быть очень увлекательным и полезным, уровень квалификации, требуемый для того, чтобы написать мало-мальское приложение, в наше время очень высокий. Задача SPL — не вам, как программисту, дать новый инструмент. Его задача дать не-программисту простой и доступный инструмент.
                  Если вы скажете, что это все не так, что таких людей, интересующихся прогаммированием нет, или что таким людям не проблема освоить, скажем, Питон и начать на нем писать программы для своих домашних нужд — то это не так. Такие люди есть, и им освоить современный язык программирования со всеми его API — большая проблема. Образовалась пропасть между «просто людьми» и программированием именно по причине сложности современных языков. Считайте меня популяризатором программирования как ХОББИ, и SPL — мой инструмент, который я делаю для таких людей. Так что бессмысленно спрашивать меня зачем нужен SPL если есть этот язык и вот этот язык, потому что если вам в голову приходит такой вопрос, то значит, что он вам, скорее всего, просто не нужен.
                  Конечно я немного лукавлю. Я сам, будучи профессиональным программистом, периодически пользуюсь собственными инструментами, которые делаю для «не профессионалов», чтобы быстро и просто решить какую-нибудь мелкую задачу — проверить алгоритм, сделать сетевое приложение чтобы обработать какой-нибудь сайт или набросать мини-игру, потому что это просто интересно. Но это — не самое главное. Главное — тот позитив, который я получаю от пользователей не-программистов, пришедших к программированию благодаря моему софту. SPL — не первый мой язык программирования, и я знаю о чем пишу. Но это — моя последняя разработка на данный момент, и в нем будет реализован весь мой опыт решения таких задач.


                  1. sophist
                    12.06.2017 09:52
                    +3

                    Если вы скажете, что это все не так, [...] что таким людям не проблема освоить, скажем, Питон и начать на нем писать программы для своих домашних нужд — то это не так.

                    Судя по вашему предположению выше, что в Python есть операторные скобки («закорючки»), с этим языком вы знакомы чуть более, чем никак. Это несколько лишает убедительности процитированное утверждение.

                    Такие люди есть, и им освоить современный язык программирования со всеми его API — большая проблема.

                    Вы хотите сказать, что вот такой код:
                    v(x,y)<=x(y)
                    #.output(v(#.sqrt,4))
                    

                    свободен от этого недостатка?

                    На возможное возражение, что начинающим необязательно пользоваться всеми возможностями языка, замечу, что ровно то же самое можно сказать и о любом «современном языке программирования», в частности, о Питоне.


                    Если желаете возразить, предлагаю действовать конструктивно: найдите конкретные фичи Python, которые, по вашему мнению, представляют проблему для освоения непрограммистами, и покажите, какую альтернативу вы предлагаете в своем языке.

                    Если будете приводить в пример такую фичу вашего языка, как небуквенные ключевые слова, то объясните, какую проблему пользователя она решает.

                    Как я понимаю, вы хотели, чтобы при использовании кириллицы для именования переменных и функций не приходилось переключать раскладку клавиатуры. Но ведь знаки ">", "<", да и "#" всё равно требуют её переключения. Есть ли другие резоны?


                    1. Mr_Kibernetik
                      12.06.2017 11:08

                      Если уж зашла речь о Питоне, то в нем только одних ключевых слов более трех десятков. И это не считая «закорючек». SPL же обходится всего несколькими «закорючками»: > < = — ?!. которые образуют около десяти визуально наглядных символических команд.
                      Кстати, по поводу синтаксиса SPL. Он не призван «решать» никакие проблемы. Он максимально просто формирует структуру кода, которая одновременно достаточно ясна и функциональна.


                      1. staticlab
                        12.06.2017 11:38

                        У Лиспа «закорючек» в синтаксисе ещё меньше, если на то пошло.


                      1. sophist
                        12.06.2017 12:21
                        +1

                        Кстати, по поводу синтаксиса SPL. Он не призван «решать» никакие проблемы.

                        Тогда к чему вы говорили вот это:
                        Задача SPL — [...] дать не-программисту простой и доступный инструмент. [...] Такие люди [непрограммисты, интересующиеся програмированием] есть, и им освоить современный язык программирования со всеми его API — большая проблема.

                        Сформулирую свой вопрос по-другому: каким образом использование небуквенных ключевых слов вместо буквенных решает задачу дать непрограммисту простой и доступный инструмент? (Удобство в переключении клавиатурной раскладки, как мы видим, не может служить аргументом).

                        Он максимально просто формирует структуру кода, которая одновременно достаточно ясна и функциональна.

                        Допустим. Но в чем преимущество вашего языка перед другими, также просто формирующими ясную и функциональную структуру кода? В каких конкретных его особенностях?

                        Представьте, например, что я такой вот непрограммист и выбираю себе язык для хобби. Я смотрю на Python и смотрю на ваш язык. Оба максимально просто формируют структуру кода, оба ясны и функциональны. Что может побудить меня предпочесть ваш язык?

                        Пока что, как я уже сказал, я вижу у вас лишь один аргумент, и он слабый. Вместо if, for, return и т.д., которые надо вводить в латинской раскладке, предлагается писать ?, >, <= и т.д., половина из которых тоже требует латинской раскладки.


                        К слову, «закорючка» в Python только одна: двоеточие. Ни операторных скобок, ни признаков конца блока (как ваши точка и знак «меньше») в нем нет.


                        1. Mr_Kibernetik
                          12.06.2017 12:45

                          Это не вопрос для ответа в одном комментарии. Чтобы оценить язык нужно с ним сначала ознакомиться. Вряд-ли один только упрощенный синтаксис записи может быть серьезным плюсом. Важна общая идеология языка в целом. Я делал SPL с оглядкой на BASIC — чтобы SPL был проще, чем BASIC и при этом имел больше возможностей, чем BASIC. Если какой-то язык программирования, не важно какой, имеет десятки ключевых слов, описание типов, требует подключения библиотек для своей полноценной работы — я его отношу к категории «сложных» и как возможного конкурента для SPL даже не рассматриваю — это другая весовая категория.


                  1. aamonster
                    12.06.2017 10:58

                    Нет-нет-нет. Если вы не программист — любая экзотика исключается сразу. Только язык, по которому есть, кого спрашивать.


          1. staticlab
            11.06.2017 22:11
            +1

            Другими словами, #. — это огромное пространство имён, состоящее из функций самого разнообразного назначения, что можно сравнить с огромным числом стандартных функций PHP. Думается, что такой дизайн языка не очень удачен для пользователя.


            1. Mr_Kibernetik
              11.06.2017 22:29
              -2

              Верно. Но в SPL есть возможность перегруппировать функции «под себя», причем даже дав им более удобные названия.
              Например, изначально есть функция вывода текста #.output, графическая функция #.drawline и математическая #.sin. Можно, например, сделать такое переназначение:

              g.line = #.drawline
              math.sin = #.sin
              o.p = #.output

              таким образом автоматически создав пространства имен «g», «math» и «o», и пользование такими «кастомными» функциями будет выглядеть так:

              g.line(100,100)
              y=math.sin(x)
              o.p(«Hello»)

              Можно просто перевести библиотечные функции в общее пространство имен, например:

              output = #.output

              То есть весь парк библиотечных функций можно кастомизировать на свой вкус, если есть такая потребность.


              1. staticlab
                11.06.2017 22:37

                Это просто присвоение ссылок, или в вашем языке функции являются сущностями первого порядка?


                1. Mr_Kibernetik
                  12.06.2017 02:32
                  +1

                  Спасибо за хороший вопрос.
                  В SPL функции первого порядка. То есть эта программа:

                  f()<=#.output
                  f()(«Text»)

                  напечатает «Text». В ней в первой строке функция F возвращает в качестве своего результата системную функцию #.OUTPUT, которая во второй строке будучи вызвана как результат работы функции F, напечатает «Text».

                  Или например эта программа напечатает число 2:

                  v(x,y)<=x(y)
                  #.output(v(#.sqrt,4))

                  здесь функция V принимает два параметра X и Y, а возвращает результат выполнения первого параметра X со вторым параметром Y в качестве параметра. Во второй строке функция V вызывается с системной функцией #.SQRT в качестве первого параметра и числом 4 в качестве второго параметра. В итоге печатается число 2 как результат #.sqrt(4)


        1. Akdmeh
          11.06.2017 19:26

          Пока писал решение на PHP и говорил, что идеальным в этом плане есть Python — вы написали решение. Спасибо!


      1. Akdmeh
        11.06.2017 19:25

        Ну вот код на PHP, у которого не лучший имидж, но он прост (я пытался сохранить логику вашего кода, поэтому немного не по PSR-1 и PSR-2, извините). На том же Python можно сделать еще лаконичнее (вообще считаю Python чуть ли не идеальным для вхождения новичкам).
        Но даже изучив PHP человек будет знаком с семейством С-подобных языков и сможет, например, со временем изучить C, C++, Python, Java. Поэтому я повторю вопрос — какая сфера применения этого языка — серверная разработка, веб, десктоп? В чем преимущества по сравнению с существующими языками?

        $text = file_get_contents('hamlet.txt');
        
        $words = preg_split('/[\s.,;!?()\[\]\'-]+/', $text);
        
        $dict = array();
        $total = 0;
        
        foreach ($words as $word)
        {
        	if (empty($word)) continue;
        	$key = strtolower($word);
        	$dict[$key] = isset($dict[$key]) ? $dict[$key] + 1 : 1;
        	$total += 1;
        }
        
        natsort($dict);
        $dict = array_reverse($dict);
        
        echo $total, ' слов; ', sizeof($dict), " уникальных слов\n";
        
        $limit = 1;
        foreach ($dict as $key => $count) {
        	echo $limit, ' : ', $key, ' = ', $count."\n";
        	$limit++;
        	if ($limit == 10) break;
        }
        


        1. Mr_Kibernetik
          11.06.2017 19:32
          -2

          Спасибо за пример на PHP. Он позволяет тем, кто не знаком ни с PHP, ни с SPL, оценить возможности и сравнить простоту кода PHP и SPL.
          Назначение SPL — хобби и повседневное программирование. Особенность SPL — простота при высоком функционале. Надеюсь в будущем, при обзоре графики и других возможностей, которые я туда добавлю, вы тоже поделитесь своим опытом, чтобы можно было на прмерах посравнивать SPL и PHP.


          1. Akdmeh
            11.06.2017 19:34
            +3

            Напишите лучше статью о том, что за язык, как пришла в голову идея, ваш ли это язык; ссылка на документацию, планы на развитие, в каких сферах удобно применять, скорость работы.
            Ну и главное — это компилятор/интерпретатор, на чем написан и т.д.


            1. Mr_Kibernetik
              11.06.2017 22:13

              Спасибо за совет! Если читателям это интересно, то конечно.


          1. staticlab
            11.06.2017 22:05

            То есть у вас будет эдакий классический Бейсик или Паскаль, в котором "из коробки" были графические функции?


            1. Mr_Kibernetik
              11.06.2017 22:10

              Да, совршенно верно.


  1. TiesP
    11.06.2017 22:40

    Чем-то похож на современный js.
    Попробовал сделать на js (который изучаю). Не уверен, что самый короткий вариант, но работает)


    const fs = require('fs');
    let total=0;
    
    const words = fs.readFileSync('./hamlet.txt', 'utf8').
    split(/["'\s\n\r\t.,;!?\-\][)(]+/).
    map((item) => item.toLowerCase()).
    reduce((r, item) => {
      r[item] = (r[item] === undefined) ? 1 : r[item] + 1;
      total++;
      return r;
    }, {});
    console.log(`${total} слов; ${Object.keys(words).length} уникальных слов`);
    
    Object.keys(words).
    sort((a, b) => words[b] - words[a]).
    reduce((r, item, i) => {
      r.push(`${i+1} : ${item} = ${words[item]}`);
      return r;
    }, []).
    forEach((item, i) => {
      if (i < 10) console.log(item);
    });


    1. Mr_Kibernetik
      11.06.2017 22:41

      Спасибо за пример!


    1. TiesP
      11.06.2017 23:47

      мда, в конце перемудрил… достаточно без reduce


      Object.keys(words).
      sort((a, b) => words[b] - words[a]).
      forEach((item, i) => {
        if (i < 10) console.log(`${i+1} : ${item} = ${words[item]}`);
      });


  1. staticlab
    11.06.2017 23:37

    Ruby:


    text = File.read('hamlet.txt')
    
    words = text
      .split(/\W/)
      .reject(&:empty?)
      .map(&:downcase)
    
    dict = words.each_with_object(Hash.new(0)) do
      |word, dict|
      dict[word] += 1
    end
    
    top = dict
      .sort_by(&:last)
      .reverse
    
    puts "#{words.size} слов; #{dict.size} уникальных слов"
    
    for i in 0..9 do
      puts "#{i+1} : #{top[i][0]} = #{top[i][1]}"
    end


    1. Mr_Kibernetik
      11.06.2017 23:46

      Спасибо за пример!


  1. impwx
    11.06.2017 23:39
    +5

    О, очередной язык программирования на Хабре! Налицо проблема с позиционированием. Вы говорите, что язык хорош для «обучения программированию». Это очень громкое и спорное утверждение, и вот почему:

    Во-первых, новичку нет смысла вкладываться в язык без развитой экосистемы. На других языках можно с самого начала применить знания — написать рабочую утилиту или сайт. А с вашим языком можно только обучиться сферическому программированию в вакууме, после чего придется все равно учить какую-то другую технологию и пользоваться ей.

    Во-вторых, новички делают ошибки. Поэтому пригодный для обучения язык должен быть максимально явным и недвусмысленным. В таком случае большинство допущенных ошибок будут по части синтаксиса, а их легко исправить. Совсем другое дело — ошибки логические, когда программа компилируется и работает, но выдает некорректный результат, потому что пользователь имел в виду одно, а компилятор предположил другое. Как пример — C# или Python в этой области хороши, а Perl — абсолютно непригоден. Я не очень глубоко вдавался в устройство вашего языка, но типизация похоже динамическая (строгая или нет?), и вместе с возможностью вернуть несколько объектов из функции за раз это выглядит довольно опасно. Если ошибся — расскажите, пожалуйста, как обстоят дела.

    В-третьих, ваш язык прививает плохой тон программирования. Все функции в глобальной области видимости (да еще с нечитаемым названием), сортировка in-place, отсутствие поддержки функционального программирования — это сомнительные дизайн-решения для 2017 года. Для неокрепших умов новичков это еще хуже, чем BASIC по словам Эдсгера Дейкстры.

    В-четвертых, без открытого исходного кода шанс вызвать хоть какой-то интерес стремятся к нулю.

    Если бы статья называлась «как я написал язык программирования для самого себя», было бы другое дело. Но для обучения оно точно не годится.


    1. Mr_Kibernetik
      12.06.2017 00:26
      -1

      Статья называется «решение конкретной задачи». Статья с названием «Как я написал язык для самого себя» еще будет.
      Целое поколение программистов вышло из знатоков языка BASIC, так что слова Дейкстры характеризуют не столько этих программистов, сколько самого Дейкстру.
      Не буду здесь в комментарии вдаваться в подробности, поскольку хотелось бы это раскрыть подробно в отдельной статье, но SPL предполагается в том числе и как язык разработки для публикации самостоятельных приложений в Microsoft Store. Хотя это, конечно, не особенность самого языка, а его конкретной реализации.
      Основное назначение SPL — повседневное программирование, хобби, обучение программированию. Не буду спорить с вами, удобен SPL для изучения программирования или нет. Мое дело предложить то, что я считаю удобным. Сможете написать программу еще более понятную и простую, чем в этой статье — и поговорим с вами об удобстве на конкретном предложенном вами примере. Пока из приведенных выше примеров я вижу, что SPL выглядит в сравнении с другими языками вполне достойно.
      Ну и самое важное. Нужно различать профессиональное программирование и программирование в качестве хобби. Это тема еще одной статьи — как современные профессиональные языки убили программирование в качестве хобби. SPL еще более прост, чем BASIC. И при этом в своем развитом варианте вполне будет удовлетворять общим потребностям программирования для любителей.


  1. impwx
    12.06.2017 11:35

    Целое поколение программистов вышло из знатоков языка BASIC
    При должной упорности можно написать что-то потрясающее вопреки объективно плохому инструменту. На хабре для этого есть целый хаб — «ненормальное программирование». Вот мой любимый пример — мультиплеерные крестики-нолики на .bat-файлах.

    поговорим с вами об удобстве на конкретном предложенном вами примере
    Разумеется, я не могу предложить вам пример, который понравится вам больше, чем собственное детище — потому что удобство это дело вкуса. Но раз вы пишете приложения под Microsoft Store, наверняка знакомы с LINQ. На нем задача решается, на мой взгляд, очень просто:
    Код
    var file = File.ReadAllText("hamlet.txt");
    var words = Regex.Split(file, @"[\s.,;!?()\[\]\'-]+");
    
    var uniqueWords = words.Select(x => x.ToLowerInvariant())
    					   .GroupBy(x => x)
    					   .ToDictionary(x => x.Key, x => x.Count());
    					   
    var topTen = uniqueWords.OrderByDescending(x => x.Value)
    					    .Take(10);


    1. Mr_Kibernetik
      12.06.2017 12:17

      В SPL пользователь при желании сам может разделить группу "#" на любые удобные ему подгруппы и переназвать функции. Например, из #.sqrt, #.drawline и #.output можно получить:

      math.sqr = #.sqrt
      gfx.line = #.drawline
      print = #.output


      1. impwx
        12.06.2017 13:19

        Но зачем заставлять пользователя каждый раз это делать?


        1. Mr_Kibernetik
          12.06.2017 13:49

          Абсолютно не требуется это каждый раз делать. Записали это в файл «x», потом подключили:

          $x


          1. staticlab
            12.06.2017 16:52
            +1

            А почему бы это не сделать автору?


            1. Mr_Kibernetik
              12.06.2017 18:20

              Не вижу в этом смысла. В любом случае не будет двух библиотечных функций с одним именем и различным назначением.


              1. impwx
                12.06.2017 18:51

                Смысл не в защите от пересечения имен, а разделении одной большой свалки функций на логические группы. Если пользователь может набрать math. и ему подскажется только список математических функций — это гораздо удобнее, чем искать нужное из списка вообще всех функций.


                1. Mr_Kibernetik
                  12.06.2017 19:02

                  У меня немного другой опыт. Пока пользователь набирает «math» он бы уже набрал нужную ему функцию «sin», «abs» или «sqrt». Да и количество функций в SPL будет не такое огромное, чтобы это могло вызвать дискомфорт. Но в любом случае спасибо за совет.


                  1. impwx
                    12.06.2017 19:20

                    Это если он заранее знает, как называется нужная функция. С математическими это еще можно предположить (хотя даже там бывают различия — например tan или tg), а вот функции для работы с графикой без подсказки не угадаешь.


  1. kolpeex
    12.06.2017 13:51

    > i, 1..10
    key = dict[i]
    #.output(i, " : ", key, " = ", dict[key])
    <

    К словарю можно обратиться по индексу и по ключу? А если ключ — число?


    1. Mr_Kibernetik
      12.06.2017 13:54

      Ключом может быть только текст. Если вы подаете число, то это будет уже обращение по индексу.
      Если ключом является число, то его конечно нужно подавать в текстовом виде.


      1. staticlab
        12.06.2017 16:58

        А что у вас происходит с массивом в таком варианте:


        arr[1] = 2
        arr[5] = 3
        arr["foo"] = 4

        А именно, когда и сколько выделяется памяти, создаются ли промежуточные пустые значения, каким образом размещаются элементы по индексам и строковым ключам?


        1. Mr_Kibernetik
          12.06.2017 18:12

          Ошибка: «Неверный тип индекса» в третьей строке. Потому что объект «arr» уже инициализировался как массив.
          Памяти в случае массива выделяется по его максимальным индексам. В случае словаря — по необходимости. Промежуточных пустых значений нет — отсутствие величины это именно ее полное отсутствие. Попытка использовать отсутствующее значение приводит к ошибке выполнения.


          1. staticlab
            12.06.2017 19:13

            Памяти в случае массива выделяется по его максимальным индексам.

            То есть при последовательной инициализации элементов массива аллокация будет происходить на каждой итерации цикла?


            1. Mr_Kibernetik
              12.06.2017 19:27

              Да. На этот счет в документации дается совет сначала записывать объект с максимальным индексом, если массив достаточно велик.


              1. staticlab
                12.06.2017 21:25

                Жесть. А со словарями тогда как жить?


                1. Mr_Kibernetik
                  12.06.2017 21:47

                  В чем жесть?
                  Чем принципиально отличается
                  int[] m = int[1000]
                  от
                  m[1000]=0
                  что аж прямо «жесть»?
                  И какие могут быть проблемы со словарями?


                  1. staticlab
                    12.06.2017 22:13
                    +1

                    Язык позиционируется как язык для неспециалистов. И вряд ли ЦА задумается о регулярных переаллокациях массива. А деградация производительности будет существенной. Притом, будет наблюдаться сильная фрагментация памяти. Тем более, m[1000] = 0 больше выглядит как хак, а не как стандартная конструкция языка.


                    Насчёт словарей: получается, что для них заранее аллоцировать необходимую память нельзя, даже если известно точное или приблизительное число элементов?


                    1. Mr_Kibernetik
                      12.06.2017 22:26

                      Если это будет не удобно или если возникнут какие-нибудь проблемы, то будет добавлена функция-выделитель памяти типа a = #.array(1000).
                      В любом случае тот функционал автоматического выделения, который есть сейчас, останется.


                    1. impwx
                      13.06.2017 10:54

                      По-моему, для новичка-непрограммиста важна простота и корректность работы, а производительность — дело десятое. Идеальным вариантом (имхо) было бы отказаться от идеи произвольной индексации и сделать два отдельных типа данных — аналоги List и Dictionary из C#.


                      1. staticlab
                        13.06.2017 11:47
                        +1

                        Согласен, но, например, в Java хотя бы используется стратегия n*1.5+1, что снижает фрагментацию памяти и ускоряет работу.


                        А по поводу корректности — мой вариант на Ruby выдаёт 4607 уникальных слов. Сейчас проверить возможности нет, но это отличается от варианта автора. Скорее всего дело в проверке разделителей: у меня это \W, у автора просто список. Вероятно, какой-то знак он упустил. Возможно, тире.


                        1. impwx
                          13.06.2017 12:07
                          +1

                          Разумеется. В C# используется стратегия n*2. Какая из них лучше — не проверял, но думаю что результаты примерно одинаковые, и явно сильно лучше, чем выделять память каждый раз под максимальный элемент массива.

                          Мне вообще не нравится идея смешивать разные структуры данных в одну. В PHP «массивом» назвали смесь разреженного списка со словарём, а с учетом нестрогой типизации ключей в нем вообще творится магия.