NAME
WordList - Specification and base class for WordList::*, modules that contain word list
VERSION
This document describes version 0.7.11 of WordList (from Perl distribution WordList), released on 2021-09-26.
SYNOPSIS
Use one of the WordList::*
modules.
DESCRIPTION
WordList::*
modules are modules that contain, well, list of words. This module, WordList
, serves as a base class and establishes convention for such modules.
WordList
is an alternative for Games::Word::Wordlist and Games::Word::Wordlist::*
. Its main difference is: WordList::*
wordlists are read-only/immutable and the modules are designed to have low startup overhead. This makes them more suitable for use in CLI scripts which often only want to pick a word from one or several lists. See "DIFFERENCES WITH GAMES::WORD::WORDLIST" for more details.
Unless you are defining a dynamic wordlist (see below), words (or phrases) must be put in __DATA__
section, one per line. Putting the wordlist in the __DATA__
section relieves perl from having to parse the list during the loading of the module. To search for words or picking some random words from the list, the module also need not slurp the whole list into memory (and will not do so unless explicitly instructed).
You must sort your words ascibetically (or by Unicode code point). Sorting makes it more convenient to diff different versions of the module, as well as performing binary search. If you have a different sort order other than ascibetical, you must set package variable $SORT
with some true value (say, frequency
).
There must not be any duplicate entry in the word list.
Dynamic and non-deterministic wordlist. A dynamic wordlist must set package variable $DYNAMIC
to either 1 (deterministic) or 2 (non-deterministic). A dynamic wordlist does not put the wordlist in the DATA section; instead, user relies on first_word()
+ next_word()
, or each_word()
, or all_words()
to get the list. A deterministic wordlist returns the same list everytime each_word()
or all_words()
is called. A non-deterministic list can return a different list for a different each_word()
or all_words()
call. See WordListRole::FirstNextResetFromEach, WordListRole::EachFromFirstNextReset, WordListRole::FromArray if you want to write a dynamic wordlist module. It is possible for a dynamic list to return unordered or duplicate entries, but it is not encouraged.
Parameterized wordlist. When instantiating a wordlist class instance, user can pass a list of key-value pairs as parameters. Normally only a dynamic wordlist would accept parameters. Parameters are defined in the %PARAMS
package variable. It is a hash of parameter names as keys and parameter specification as values. Parameter specification follows function argument metadata specified in Rinci::function.
Examples. Examples can be specified in @EXAMPLES
package variable. The structure is similar to Rinci function's examples
property. For example:
# in lib/WordList/Test/Dynamic/RandomWord/1000.pm
@EXAMPLES = (
{
summary => '1000 random words, each 10 to 15 characters long',
args => {min_len=>10, max_len=>15},
}
);
DIFFERENCES WITH GAMES::WORD::WORDLIST
Since this is a non-compatible interface from Games::Word::Wordlist, I also make some other changes:
Namespace is put outside
Games::
Because obviously word lists are not only useful for games.
Namespace is more language-neutral and not English-centric
English wordlists are put under
WordList::EN::*
. Other languages have their own subnamespaces, e.g.WordList::FR::*
orWordList::ID::*
. Aside from language subnamespaces, there are also other subnamespaces:WordList::Phrase::$LANG::*
,WordList::Password::*
,WordList::Domain::*
,WordList::HTTP::*
, etc.Interface is simpler
This is partly due to the list being read-only. The methods provided are just:
-
pick
(pick one or several random entries, without duplicates or with)-
word_exists
(check whether a word is in the list)-
each_word
(run code for each entry)-
all_words
(return all the words in a list)A couple of other functions might be added, with careful consideration.
More extensions
Some roles, subclasses, or alternate implementations are provided. For example, since most wordlist are alphabetically sorted, a binary search can be performed in
word_exists()
. There is a role, WordListRole::BinarySearch, that does that and can be mixed in. An even faster version ofword_exists()
using bloom filter is offered by WordListRole::Bloom. A faster version of pick() that does random seeking is offered by WordListRole::RandomSeekPick.
SUBCLASSING OR CREATING ROLES
If you want to get the word list from another filehandle source, e.g. a gzipped file, you just need to override reset_iterator()
. Your reset_iterator()
needs to set the 'fh' attribute to the filehandle. The default first_word()
calls reset_iterator()
and reads a line from the filehandle. The default next_word()
just reads another line from the filehandle. each_word()
is implemented in terms of first_word()
and next_word()
, and word_exists()
, pick()
, and all_words()
are implemented in terms of each_word()
.
METHODS
new
Usage:
$wl = WordList::Module->new([ %params ]);
Constructor.
each_word
Usage:
$wl->each_word($code)
Call $code
for each word in the list. The code will receive the word as its first argument.
If code return -2 will exit early.
first_word
Another way to iterate the word list is by calling "first_word" to get the first word, then "next_word" repeatedly until you get undef
.
next_word
Get the next word. See "first_word" for more details.
reset_iterator
Reset iterator. Basically "first_word" is equivalent to reset_iterator
+ "next_word".
pick
Usage:
@words = $wl->pick([ $num=1 [ , $allow_duplicates=0 ] ])
Examples:
($word) = $wl->pick;
@words = $wl->pick(3);
Pick $n
(default: 1) random word(s) from the list, without duplicates (unless $allow_duplicates
is set to true). If there are less then $n
words in the list and duplicates are not allowed, only that many will be returned.
The algorithm used is from perlfaq ("perldoc -q "random line""), which scans the whole list once (a.k.a. each_word() once). The algorithm is for returning a single entry and is modified to support returning multiple entries.
word_exists
Usage:
$wl->word_exists($word) => bool
Check whether $word
is in the list.
Algorithm in this implementation is linear scan (O(n)). Check out WordListRole::BinarySearch for an O(log n) implementation, or WordListRole::Bloom for O(1) implementation.
all_words
Usage:
$wl->all_words() => list
Return all the words in a list, in order. Note that if wordlist is very large you might want to use "each_word" instead to avoid slurping all words into memory.
FAQ
Why does pick() return "1"?
You probably write this:
$word = $wl->pick;
instead of this:
($word) = $wl->pick;
pick()
returns a list and in scalar context it returns the number of elements in the list which is 1. This is a common context trap in Perl.
HOMEPAGE
Please visit the project's homepage at https://metacpan.org/release/WordList.
SOURCE
Source repository is at https://github.com/perlancar/perl-WordList.
SEE ALSO
Related projects: ArrayData, HashData, TableData are newer projects inspired by WordList. I plan to publish newer wordlists as ArrayData::*
modules. But WordList will still exist and stabilize its API.
WordListRole::*
modules.
WordList::*
modules.
CLI's are provided in App::wordlist (wordlist), App::WordListUtils (e.g. list-wordlist-modules, etc).
AUTHOR
perlancar <perlancar@cpan.org>
CONTRIBUTING
To contribute, you can send patches by email/via RT, or send pull requests on GitHub.
Most of the time, you don't need to build the distribution yourself. You can simply modify the code, then test via:
% prove -l
If you want to build the distribution (e.g. to try to install it locally on your system), you can install Dist::Zilla, Dist::Zilla::PluginBundle::Author::PERLANCAR, and sometimes one or two other Dist::Zilla plugin and/or Pod::Weaver::Plugin. Any additional steps required beyond that are considered a bug and can be reported to me.
COPYRIGHT AND LICENSE
This software is copyright (c) 2021, 2020, 2018, 2017, 2016 by perlancar <perlancar@cpan.org>.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
BUGS
Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=WordList
When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.