> For the complete documentation index, see [llms.txt](https://trizen.gitbook.io/perl6-rosettacode/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://trizen.gitbook.io/perl6-rosettacode/programming_tasks/r/rosetta-code/rank_languages_by_number_of_users.md).

# Rank languages by number of users

Use the mediawiki API rather than web scraping since it is much faster and less resource intensive. Show languages with more than 25 users since that is still a pretty short list and to demonstrate how tied rankings are handled. Change the **$minimum** parameter to adjust what the cut-off point will be.

This is all done in a single pass; ties are not detected until a language has the same count as a previous one, so ties are marked by a **T** next to the count indicating that **this** language has the same count as the **previous**.

```perl
use HTTP::UserAgent;
use URI::Escape;
use JSON::Fast;

my $client = HTTP::UserAgent.new;

my $url = 'https://rosettacode.org/w';

my $start-time = now;

say "========= Generated: { DateTime.new(time) } =========";

my $lang = 1;
my $rank = 0;
my $last = 0;
my $tie = ' ';
my $minimum = 25;

.say for
    mediawiki-query(
        $url, 'pages',
        :generator<categorymembers>,
        :gcmtitle<Category:Language users>,
        :gcmlimit<350>,
        :rawcontinue(),
        :prop<categoryinfo>
    )

    .map({ %( count => .<categoryinfo><pages> || 0,
              lang  => .<title>.subst(/^'Category:' (.+) ' User'/, ->$/ {$0}) ) })

    .sort( { -.<count>, .<syntaxhighlight lang="text"> } )

    .map( { last if .<count> < $minimum; display(.<count>, .<syntaxhighlight lang="text">) } );

say "========= elapsed: {(now - $start-time).round(.01)} seconds =========";

sub display ($count, $which) {
    if $last != $count { $last = $count; $rank = $lang; $tie = ' ' } else { $tie = 'T' };
    sprintf "#%3d  Rank: %2d %s  with %-4s users:  %s", $lang++, $rank, $tie, $count, $which;
}

sub mediawiki-query ($site, $type, *%query) {
    my $url = "$site/api.php?" ~ uri-query-string(
        :action<query>, :format<json>, :formatversion<2>, |%query);
    my $continue = '';

    gather loop {
        my $response = $client.get("$url&$continue");
        my $data = from-json($response.content);
        take $_ for $data.<query>.{$type}.values;
        $continue = uri-query-string |($data.<query-continue>{*}».hash.hash or last);
    }
}

sub uri-query-string (*%fields) {
    join '&', %fields.map: { "{.key}={uri-escape .value}" }
}
```

#### Output:

```
========= Generated: 2022-09-02T20:59:20Z =========
#  1  Rank:  1    with 441  users:  C
#  2  Rank:  2    with 321  users:  Java
#  3  Rank:  3    with 319  users:  Python
#  4  Rank:  4    with 314  users:  C++
#  5  Rank:  5    with 291  users:  JavaScript
#  6  Rank:  6    with 190  users:  PHP
#  7  Rank:  7    with 186  users:  Perl
#  8  Rank:  8    with 167  users:  SQL
#  9  Rank:  9    with 151  users:  UNIX Shell
# 10  Rank: 10    with 133  users:  Pascal
# 11  Rank: 11    with 132  users:  BASIC
# 12  Rank: 11 T  with 132  users:  C sharp
# 13  Rank: 13    with 115  users:  Haskell
# 14  Rank: 14    with 107  users:  Ruby
# 15  Rank: 15    with 94   users:  Fortran
# 16  Rank: 16    with 75   users:  Visual Basic
# 17  Rank: 17    with 72   users:  Scheme
# 18  Rank: 18    with 70   users:  Prolog
# 19  Rank: 19    with 68   users:  AWK
# 20  Rank: 19 T  with 68   users:  Lua
# 21  Rank: 21    with 66   users:  Common Lisp
# 22  Rank: 22    with 61   users:  HTML
# 23  Rank: 23    with 55   users:  X86 Assembly
# 24  Rank: 24    with 50   users:  Forth
# 25  Rank: 25    with 49   users:  Batch File
# 26  Rank: 26    with 47   users:  Assembly
# 27  Rank: 27    with 45   users:  Bash
# 28  Rank: 27 T  with 45   users:  MATLAB
# 29  Rank: 29    with 42   users:  Lisp
# 30  Rank: 30    with 41   users:  APL
# 31  Rank: 30 T  with 41   users:  Erlang
# 32  Rank: 32    with 40   users:  Delphi
# 33  Rank: 32 T  with 40   users:  R
# 34  Rank: 34    with 39   users:  J
# 35  Rank: 34 T  with 39   users:  Visual Basic .NET
# 36  Rank: 36    with 38   users:  Go
# 37  Rank: 36 T  with 38   users:  Tcl
# 38  Rank: 38    with 37   users:  COBOL
# 39  Rank: 39    with 36   users:  Smalltalk
# 40  Rank: 40    with 35   users:  Brainf***
# 41  Rank: 40 T  with 35   users:  Objective-C
# 42  Rank: 42    with 34   users:  Clojure
# 43  Rank: 43    with 33   users:  Mathematica
# 44  Rank: 44    with 30   users:  OCaml
# 45  Rank: 45    with 28   users:  LaTeX
# 46  Rank: 46    with 27   users:  AutoHotkey
# 47  Rank: 46 T  with 27   users:  Emacs Lisp
# 48  Rank: 46 T  with 27   users:  PostScript
# 49  Rank: 46 T  with 27   users:  REXX
# 50  Rank: 50    with 26   users:  Perl 6
# 51  Rank: 50 T  with 26   users:  Sed
# 52  Rank: 52    with 25   users:  CSS
# 53  Rank: 52 T  with 25   users:  Scala
# 54  Rank: 52 T  with 25   users:  VBScript
========= elapsed: 1.48 seconds =========

========= elapsed: 1.45 seconds =========
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://trizen.gitbook.io/perl6-rosettacode/programming_tasks/r/rosetta-code/rank_languages_by_number_of_users.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
