Idio Functions¶
This is not a comprehensive list but rather a flavour.
Some functions are closely tied to certain value types and others are a bit more generic.
Values¶
Constants¶
We can test for some kinds of constants with boolean?, null?, void?, eof-object?.
Numbers¶
Numbers are implemented as either fixnums or bignums. Fixnums are fairly lightweight, bignums less so.
Test generically with number? and integer? and more specifically with fixnum? and bignum?.
Use read-number to turn a string into a number.
Basic arithmetic with +, -, * and /.
Arithmetic comparisons with lt, le, eq, ne, ge and gt.
All of the above four arithmetic and five comparison functions have
binary infix operators such that x op y becomes
binary-op x y with corresponding functions binary-+, etc..
Further arithmetic with abs, quotient, expt (x to the power y), sqrt and exp (Euler’s number to the power x) with the complementary log (natural logarithm).
Trig with cos, sin, tan and atan, acos and asin.
For bignums you can test for real? (not an integer!) and exactness with exact? and inexact?. You can extract the mantissa and exponent.
Unicode¶
Test with unicode? and compare with unicode=?.
If your module has imported the unicode module (the default Idio module does) then you’ll have a few
more useful Unicode Category and Property predicates available:
Alphabetic?, Decimal_Number?, Lowercase?, Uppercase?, Titlecase_Letter?, Punctuation?, Symbol?,
White_Space? and so on.
There are a couple of transformer functions: , ->Uppercase, ->Lowercase, ->Titlecase.
Strings¶
Test with string? and pathname?.
The number of code points in the string is given by string-length and you can get individual code points with string-ref.
You can change a code point with string-set! or all of them with string-fill! but you can’t put a “wider” code point into a “narrower” string.
Use append-string (or concatenate-string) to join strings (or a list of strings) together and join-string to use a delimiter.
Get the index of a code point with string-index or string-rindex.
You can explicitly get a substring of another with substring noting that the second index is up to but not
including – for example, the string up to where string-index said
some code point was.
Split strings up with fields (using IFS) or split-string (using IFS by default) or split-string-exactly which is more exacting than the traditional shell “splitting on whitespace”, say.
You can do some string comparisons though it is worth noting that, for consistency, these rather inefficiently convert the string into UTF-8 and then call either strncmp(3) or strncasecmp(3) (as appropriate). See string<?, string<=?, string=?, string>=?, string>? and their case-insensitive variants string-ci<?, etc..
Symbols and Keywords¶
Handles¶
Test a handle with handle?, input-handle?, output-handle?, eof? and closed-handle?, the result of close-handle.
Handle attributes include handle-line, handle-pos and handle-name.
Access the contents with read-line, read-lines and read-char.
Output can be broadly two flavours: the printed representation of an object, something the reader might read back in; and a display representation, something the user might want to experience. This broadly only affects strings and characters:
printed |
displayed |
|---|---|
|
|
|
|
Writing to (output!) handles has some basic methods:
for printing, write any value and puts a string, in particular
for displaying, display and edisplay to the current error handle
For general formatted Printing, hprintf (handle-printf) is the function underlying printf, eprintf to the current error handle and sprintf to get a string.
You can change the position of a handle, like a file position, with seek-handle and rewind-handle.
File Handles¶
Test a file handle with file-handle?, input-file-handle? and output-file-handle?.
Create a file handle with open-input-file and open-output-file or the more general open-file which accepts an fopen(3)-style mode string.
Get the underlying file descriptor with file-handle-fd.
String Handles¶
Test a string handle with string-handle?, input-string-handle? and output-string-handle?.
Create a string handle with open-input-string and open-output-string.
Get the accumulated string from an output string handle with get-output-string.
General Functions¶
Conditional Expressions¶
The canonical conditional expression is if
with cond being the
if .. elif .. elif .. else .. variant. cond has an extremely
powerful => operator implementing an anaphoric if.
if breaks a few conventions in that it doesn’t use then or
else, it is simply:
if condition consequent alternative.
If either of consequent or alternative are simple
values then, together with the one line per expression, it can look
awkward.
Here, the consequent, #n, feels lost in front of the
opening brace of the alternative.
if (pair? a) #n {
eprintf "not a pair!\n"
}
Not great.
when is syntactic sugar for if where there is no
alternate clause. It might scan better for maintainers.
Use not to invert the boolean result with unless implicitly doing it for you.
Selecting between known cases (think: explicit values) is done with
case. regex-case and
pattern-case, in particular, offer something
closer to the shell’s case statement.
Looping Expressions¶
The do expression loops over a body of code,
initialising then incrementing some loop variables in a near identical
fashion for C’s for (init; test; step) body
statement.
The only meaningful difference is that in addition to the
test for end of loop you can specify some code to determine
the value to return from do. Remember, everything returns a
value.
Iteration Over Collections¶
You can either map over a list, array or keys of a hash table or loop with for-each depending on whether you want to collect the results of each iteration.
You can iterate over lists with fold-left and fold-right.
Equality¶
Things can be:
(File) Predicates¶
You can ask the usual file predicate questions with f?, d?, l? etc. with r?, w? and x? available.
Printing¶
Through printf etc. you can control how
values are printed. Primarily numbers
with the usual %d/%x variants. Fixnums and some integer
C types can use a %b binary output format.
If you define a structure you can control how it is printed.
Most of the libc structures are similarly controlled – albeit, changing that format requires a recompile!
Sorting¶
Sorting revolves around the sort function which takes an optional accessor argument which allows indirect sorting.
Hence there are sort-mtime, sort-size etc. functions which take a list of filenames and sort them by some stat(2) attribute.
Loading Code¶
loading is based on the load function.
load will always run through the file it loads. You can effect a
load-once system with a combination of require’ing a file which provide’s some
feature.
You can import a module of code – which uses the
require/provide mechanism as an aside – and updates the set
of names you can use in your code.
Matching¶
Use regex-case and the simplified pattern-case for POSIX regex pattern matching.
The underlying standard library regcomp and regexec functions are available for more direct use.
Path Manipulation¶
It’s not quite as easy to manipulate PATHs in Idio as in the shell but there is a port of some Bash functions to manipulate PATHs that might be quite useful.
Only append /usr/local/bin if it is a directory:
path-append 'PATH "/usr/local/bin" :test d?
d?, here, is the file predicate d? and is just a
regular function meaning you can write your own with more bespoke
considerations.
Globbing¶
File name globbing can’t work in Idio in the same way it
works in a shell because Idio allows (most of) the globbing
meta-characters (*, ?, [) to be valid code points in
symbols/variable names.
You can workaround this if you quote the glob expression (or at least
ensure that it is a symbol – periods in filenames, .’s, are
inconvenient):
ls -l '*.c
Otherwise, you’ll need to call the glob function directly which will return a list of matches.
glob can return no matches, the empty list, #n, so you will
need to test before passing the list onto an external command:
files := glob "*.c"
if (null? files) {
eprintf "WARNING: no files matched *.c\n"
} {
ls -l files
}
Here, files, a list of file names, will have been expanded out as one of the arguments to the external command ls.
Note
You might be tempted to cut to the chase with:
ls -l (glob "*.c")
which is fine until it breaks. If glob returns no matches,
ie. #n then you will get an ^rt-command-argv-type-error as
there is no sensible stringified representation of #n for
external commands. ls will not be run.
Indexing¶
Causing plenty of annoyance is the . value-index operator.
The goal is a Templates::Toolkit / Jinja2-style accessor method which does something sensible for lists, arrays, hash tables, strings, appropriately tagged C structures and so on.:
arr := #[ 1 2 3 ]
arr.0 ; 1
arr.2 = 99 ; #[ 1 2 99 ]
str := "hello"
str.0 ; #\h
sb := libc/stat "."
sb.st_ino ; 69256525
Note
In this particular case trying to set an element of the string will fail as it is flagged as a const string (because it was constructed by the reader). You would need to copy-string first.
str := copy-string "hello"
str.1 = #\E ; "hEllo"
Not all C structures have a setter.
Without any form of Type Inference then this must query the value type before continuing but it is considerably more readable.
The indexing element can be a variable so that arr.i does
the right thing. Of course, if st_ino is a variable in your code
then the previous expression sb.st_ino might have unintended
consequences. You can force a name/symbol with quote: sb.'st_ino.
The indexing element can also be a function in which case the
function is applied to the value, that is v.f becomes an
invocation of f v.
This is useful for splitting a line into fields:
Idio> (read-line).fields
hello world
#[ "hello world" "hello" "world" ]
Here, fields has returned an array of the original string and the
IFS-separated words in the string.
Note
The reason . is annoying is that we are all prone to writing
shell-like statements such as
ls *.txt
which value-index can’t figure out.
Last built at 2026-01-04T22:40:02Z+0000 from da47fd3 (dev)