<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/css" href="/css/atom-browser.css" ?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">	<title>Perturb.org - Scott's Geek Blog</title>
	<modified>2026-09-25T05:36:03-07:00</modified>	<link rel="alternate" type="text/html" href="http://www.perturb.org" />	<tagline>Geek blog</tagline>
	<id>tag:www.perturb.org,2026://09</id>
	<generator>Perturb ATOM v0.1</generator>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1464/" />
		<title mode="escaped">Linux: List running services</title>
		<modified>2026-09-19T08:57:22-07:00</modified>
		<issued>2026-09-19T08:57:22-07:00</issued>
		<created>2026-09-19T08:57:22-07:00</created>
		<id>http://www.perturb.org/display/entry/1464/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

Just came across this quick command to show running services. <br />
 <br />
``` <br />
systemctl list-units --type=service --state=running <br />
```
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1463/" />
		<title mode="escaped">Perl: Split a string on a delimiter, but respect quotes</title>
		<modified>2026-09-04T16:24:55-07:00</modified>
		<issued>2026-09-04T16:24:55-07:00</issued>
		<created>2026-09-04T16:24:55-07:00</created>
		<id>http://www.perturb.org/display/entry/1463/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

It's a common practice to split a string on a delimiter like a comma or semi-colon. If your input data contains the delimiter in quotes you need to respect that and **not** split there. I wrote a simple function to handle 99% of the use cases for splitting in this manner. <br />
 <br />
```perl <br />
quote_split('foo, bar, baz');   # ('foo', 'bar', 'baz') <br />
quote_split("foo, 'bar, baz'"); # ('foo', 'bar, baz') <br />
``` <br />
 <br />
```perl <br />
# Split a string on commas, but respect single and double quotes with commas <br />
sub quote_split { <br />
    my ($str, $separator) = @_; <br />
    $separator //= ","; <br />
    if (!length($separator)) { <br />
        die("quote_split separator cannot be empty\n"); <br />
    } <br />
 <br />
    my $separator_re = quotemeta($separator); <br />
    my @items; <br />
 <br />
    while ($str =~ /\G\s*(?: <br />
        "((?:\\.|[^"\\])*)"   # Double-quoted <br />
        | '((?:\\.|[^'\\])*)' # Single-quoted <br />
        | ((?:(?!$separator_re)[\s\S])+) # Unquoted <br />
    )\s*(?:$separator_re|\z)/gcx) { <br />
 <br />
        my $item = $1 // $2 // $3; <br />
 <br />
        push(@items, $item); <br />
    } <br />
 <br />
    return @items; <br />
} <br />
```
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1462/" />
		<title mode="escaped">Perl: Basic YAML parsing in a copy/pasteable function</title>
		<modified>2026-08-26T13:51:35-07:00</modified>
		<issued>2026-08-26T13:51:35-07:00</issued>
		<created>2026-08-26T13:51:35-07:00</created>
		<id>http://www.perturb.org/display/entry/1462/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

I need very basic YAML parsing in Perl, mostly for reading configuration files. There aren't any great options in Perl core, and I only need a subset of YAML (basic scalars, arrays, and hashes), so I worked up a simple copy/pasteable function.  <br />
```perl <br />
my $x = yaml_parse($yaml_str); <br />
``` <br />
 <br />
This implementation supports: nesting, scalars, arrays, and hashes, but is missing `null` / `~`, booleans, and complex quotes. <br />
 <br />
```perl <br />
sub yaml_parse { <br />
	return {} unless defined $_[0] && length $_[0]; <br />
	my %data; my $root = \%data; my @st = ([-1, \$root]); <br />
	for my $line (split /\n/, $_[0]) { <br />
		$line =~ s/\r$//; <br />
		next if $line =~ /^\s*(?:$|---\s*$|#)/; <br />
		if ($line =~ /^(\s*)-\s*(.*)$/) { <br />
			my ($n, $v) = (length($1), $2); <br />
			pop @st while $n < $st[-1][0]; my $cur = ${$st[-1][1]}; <br />
			die "yaml_parse: array without parent: $line" if @st == 1; <br />
			$cur = ${$st[-1][1]} = [] if ref $cur eq 'HASH' && !%$cur; <br />
			die "yaml_parse: mixed array/hash" if ref $cur ne 'ARRAY'; <br />
			$v =~ s/^\s+|\s+$//g; $v =~ s/^(['"])(.*)\1$/$2/s; <br />
			$v += 0 if $v =~ /^-?\d+(?:\.\d+)?$/; if ($v =~ /^([\w\-\.\/]+):\s*$/) { <br />
			push(@$cur, my $el = {$1 => {}}); push(@st, [$n + 2, \$el->{$1}]); next; } <br />
			push(@$cur, $v); <br />
		} elsif ($line =~ /^(\s*)([\w\-\.\/]+)\s*:\s*(.*)$/) { <br />
			my ($n, $key, $v) = (length($1), $2, $3); <br />
			pop @st while $n <= $st[-1][0]; my $cur = ${$st[-1][1]}; <br />
			die "yaml_parse: '$key' under array" if ref $cur eq 'ARRAY'; <br />
			$v =~ s/\s+$//; $v =~ s/^\s+//; $v =~ s/^(['"])(.*)\1$/$2/s; <br />
			if ($v =~ /^\[(.*)\]$/) { <br />
				my @a = grep { length } map { s/^\s+|\s+$//gr =~ s/^(['"])(.*)\1$/$2/sr } split /,/, $1; <br />
				for (@a) { $_ += 0 if /^-?\d+(?:\.\d+)?$/ } $v = \@a; <br />
			} else { $v += 0 if $v =~ /^-?\d+(?:\.\d+)?$/; } <br />
			if (ref $v or length $v) { $cur->{$key} = $v } <br />
			else { $cur->{$key} = {}; push(@st, [$n, \$cur->{$key}]) } <br />
		} else { warn "yaml_parse: ignoring: $line\n" } <br />
	} return \%data; <br />
} <br />
``` <br />
 <br />
`YAML::XS` is definitely the best Perl YAML parser, but it can be overkill if all you need is simple parsing. <br />
 <br />
**Update:** I wrote some [unit tests](https://www.perturb.org/code/yaml_parse.pm) to go along with this.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1461/" />
		<title mode="escaped">Javascript: Sluz sandbox</title>
		<modified>2026-08-19T18:50:14-07:00</modified>
		<issued>2026-08-19T18:50:14-07:00</issued>
		<created>2026-08-19T18:50:14-07:00</created>
		<id>http://www.perturb.org/display/entry/1461/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

I ported my [Sluz](https://github.com/scottchiefbaker/sluz) templating engine from PHP to [JavaScript](https://github.com/scottchiefbaker/js-Template-Sluz). It's now possible to run a full Sluz installation entirely in-browser. As a proof-of-concept I ported the [Sluz Sandbox](https://www.perturb.org/code/sluz-sandbox-js/) to use the JS version of library. Now you can test and validate Sluz code 100% in-browser.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1460/" />
		<title mode="escaped">Hardware required to run on frontier level AI model</title>
		<modified>2026-08-13T13:50:43-07:00</modified>
		<issued>2026-08-13T13:50:43-07:00</issued>
		<created>2026-08-13T13:50:43-07:00</created>
		<id>http://www.perturb.org/display/entry/1460/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

AI models like Claude Opus and ChatGPT 5.6 are called "frontier" (i.e. top of the line). There are several fully open source frontier level AI models that are available to download for free. I ran the specs on what it would take to run a frontier level model. <br />
 <br />
> For inference of a frontier model (400B-1T+ params): <br />
> - Minimum (4-bit quantized): ~200-500GB VRAM -> 4-8x H100 80GB GPUs <br />
> - FP16/half precision: ~800GB-2TB VRAM -> 10-32x H100 80GB GPUs <br />
> - System RAM: 512GB+ <br />
> - Interconnect: NVLink or InfiniBand between GPUs <br />
> - Storage: Several hundred GB for model weights <br />
> For training: 10,000-100,000+ GPU-hours on H100-class hardware, multi-million dollar cluster, weeks of continuous run time. <br />
> No single consumer GPU can run a frontier model - even an RTX 4090 (24GB) is about 10-30x short of VRAM needed for even a heavily quantized frontier model. <br />
 <br />
If you just want to host a "good" AI model it requires 8x GPUs with 80GB of VRAM each. <br />
  <br />
It's about $300k to get in the door for a SINGLE server to run AI you can ask questions
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1459/" />
		<title mode="escaped">Perl: romuduojr PRNG</title>
		<modified>2026-08-13T09:37:13-07:00</modified>
		<issued>2026-08-13T09:37:13-07:00</issued>
		<created>2026-08-13T09:37:13-07:00</created>
		<id>http://www.perturb.org/display/entry/1459/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

Another day, another PRNG ported to Perl. Today is [romuduojr](https://www.perturb.org/code/romujr.pl) from [romu-random.org](https://www.romu-random.org/). Pretty simple 64bit PRNG.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1458/" />
		<title mode="escaped">Perl: A simple module that doubles as a script</title>
		<modified>2026-08-01T12:02:05-07:00</modified>
		<issued>2026-08-01T12:02:05-07:00</issued>
		<created>2026-08-01T12:02:05-07:00</created>
		<id>http://www.perturb.org/display/entry/1458/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

I have a small Perl script that defines a handful of functions. Perl allows you to make a library that doubles as a script when called directly. Using `caller()` you can determine if your script was loaded via a `require()` call, or called directly. This allows you to export functions if called as a library, but run code if called directly via: `perl my_lib.pl`. <br />
 <br />
```perl <br />
# my_lib.pl <br />
if (!caller()) { <br />
    say greet("Scott"); <br />
} <br />
 <br />
sub greet { <br />
    my $name = shift(); <br />
 <br />
    return "Hello $name"; <br />
} <br />
 <br />
1; # Required if you load as a library <br />
``` <br />
 <br />
Use a `require()` call to load the module and get access to the `greet()` function. <br />
 <br />
```perl <br />
# main.pl <br />
require("/path/my_lib.pl"); <br />
 <br />
say greet("Foo"); <br />
```
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1457/" />
		<title mode="escaped">Summary of each book in the Odyssey</title>
		<modified>2026-07-15T07:57:37-07:00</modified>
		<issued>2026-07-15T07:57:37-07:00</issued>
		<created>2026-07-15T07:57:37-07:00</created>
		<id>http://www.perturb.org/display/entry/1457/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

### The Odyssey by Homer <br />
 <br />
1. Odysseus's house is full of suitors eating all his food and drinking his wine waiting for Athena to choose a new husband <br />
2. Telemachus calls a council of suitors to try and get rid of them, but the mock him and decide to stay <br />
3. Telemachus sails to Pylos to meet King Nestor and ask about his father's Whereabouts <br />
4. Telemachus reaches Sparta and learns his father is trapped on Calypso's island. The suitors plan ambush and kill Telemachus when he returns <br />
5. Odysseus builds a raft and sails for 17 days besieged by Poseidon's wrath. The raft is destroyed and he swims to shore. <br />
6. Nausicaa finds Odysseus and takes him to her father's house for a weird washing party. She directs him to her royal parents. <br />
7. The king senses Odysseus greatness and offers his daughter in marriage but Odysseus declines and only wants to return home. <br />
8. The Phaeacian compete in sports style games and recruit Odysseus. He says he is too old and worn out from the war. <br />
9. Odysseus gets captured by a huge cyclops and kept in a cave. Odysseus blinds the Cyclops with a flame stick and escapes to his boat taunting the cyclops as he leaves. <br />
10. Circe turns Odysseus's men into pigs and tempts Odysseus into her bed. He makes her swear an oath she won't harm him on his quest. She tells them they must go to the underworld next. <br />
11. Odysseus travels to the underworld and meets on his dead crewmen who fell off Circe's roof and broke his neck. He also meets a ghost who looks like his mother and it causes him grief. <br />
12. Odysseus is warned about the Siren's call. He tells his men to bind him to the mast and ignore his pleas for freedom. The men put wax in their ears and row past the Sirens. His men, starving, slaughter a sacred cow so Zeus destroys their ship and drowns everyone except Odysseus. <br />
13. Odysseus makes it back to Ithaca, but he doesn't recognize the location. Athena transforms him into a shepherd and tells him to go see the man in charge of his pigs. <br />
14. Odysseus meets the swineherd who welcomes him warmly without recognizing him. They share a meal and stories of his travels. <br />
15. Telemachus heads back to Ithaca after Athena warns him of the suitors ambush. Odysseus reveals his identity to the swineherd and they head to Oddysseus's home. <br />
16. Telemachus arrives at the swineherds home and meets his father who is still disguised. The reunite and plot to murder the suitors. <br />
17. The three travel to Odysseus's home and the goatherd mocks and kicks him. Odysseus ignores him and meets his dog who recognizes him even in disguise. The suitors assault and insult the disguised Odysseus. <br />
18. A beggar arrives at the house and challenges Odysseus, but Odysseus knocks his down pretty easily. Eurymachus throws a stool at Odysseus, while he observes the suitors behavior. <br />
19. Odysseus and Telemachus remove the weapons from the hall. Nurse Eurycleia recognizes the disguised Odysseus by a scar on his foot, but he swears her to secrecy. <br />
20. Theoclymenus foresees doom for the suitors, prophesying their impending death, but they mock him and dismiss his warning. <br />
21. Penelope brings out Odysseus's great bow and announces a contest to win her hand. The suitors all fail to string the bow, Odysseus steps up, strings the bow and shoots the arrow through twelve axes heads and wins the contest.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1456/" />
		<title mode="escaped">Git: Keep two branches in sync</title>
		<modified>2026-06-15T09:24:42-07:00</modified>
		<issued>2026-06-15T09:24:42-07:00</issued>
		<created>2026-06-15T09:24:42-07:00</created>
		<id>http://www.perturb.org/display/entry/1456/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

I have a Git repository with a primary branch that I maintain actively. I also have a separate feature branch that I'd like to keep in sync with the main branch, and alert if there are any conflicts *immediately*. Using Git hooks you can script automatically pulling each new commit from the primary branch to the feature branch. <br />
 <br />
Create a `.git/hooks/post-commit` file and put these contents in it: <br />
 <br />
```bash <br />
#!/bin/sh <br />
 <br />
SRC="main" <br />
DST="feature" <br />
 <br />
branch=$(git branch --show-current) <br />
 <br />
if [ "$branch" = "$SRC" ]; then <br />
    commit=$(git rev-parse HEAD) <br />
 <br />
    git checkout $DST && <br />
    git cherry-pick "$commit" && <br />
    git checkout main <br />
fi <br />
``` <br />
 <br />
If there are conflicts, Git errors out immediately and leaves you on the feature branch to manually resolve the conflict.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1455/" />
		<title mode="escaped">Using rsync to keep two directories in sync</title>
		<modified>2026-05-20T11:40:26-07:00</modified>
		<issued>2026-05-20T11:40:26-07:00</issued>
		<created>2026-05-20T11:40:26-07:00</created>
		<id>http://www.perturb.org/display/entry/1455/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

I have two directories with (mostly) the same content that I want to keep in sync. Specifically I want to make sure that the newest version of each file is synced to the other directory. This allows me to update a file on either side, and that version will propagate to the other. You can do this with a bi-directional `rsync` command: <br />
 <br />
```bash <br />
rsync --update -av /dir/a/ /dir/b/ <br />
rsync --update -av /dir/b/ /dir/a/ <br />
``` <br />
 <br />
Using `--update` tells `rsync` to skip files on the receiving side that are newer. If you sync `a` -> `b` and then `b` -> `a` you end up with both locations having the newest copy of each file.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1454/" />
		<title mode="escaped">Perl: ULID generation</title>
		<modified>2026-04-26T18:58:48-07:00</modified>
		<issued>2026-04-26T18:58:48-07:00</issued>
		<created>2026-04-26T18:58:48-07:00</created>
		<id>http://www.perturb.org/display/entry/1454/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

[ULID's](https://github.com/ulid/spec) are an interesting way to generate globally unique identifiers. Here is a quickie Perl implementation to generate ULIDs. This implementation does **not** include the intra-millisecond monotonic increment however. If that feature is important to you consider checking out a more full-featured implementation like [ULID::Tiny](https://github.com/scottchiefbaker/perl-ULID-Tiny). <br />
 <br />
```perl <br />
for (1 .. 5) { <br />
    say(ulid()); <br />
} <br />
``` <br />
 <br />
```perl <br />
sub ulid { <br />
    my $ts    = $_[0] // time() * 1000; <br />
    my $bytes = substr(pack("Q>", $ts), 2, 6); <br />
 <br />
    # Append 10 random bytes <br />
    $bytes .= pack 'C*', map { int(rand(256)) } 1 .. 10; <br />
 <br />
    # base32 encoding <br />
    my $bits  = '00' . unpack('B*', $bytes); <br />
 <br />
    # Chars to use for base32 <br />
    my @chars = split(//, '0123456789ABCDEFGHJKMNPQRSTVWXYZ'); <br />
 <br />
    my $result = ''; <br />
    for (my $i = 0; $i < 130; $i += 5) { <br />
        my $index = oct('0b' . substr($bits, $i, 5)); <br />
        $result .= $chars[$index]; <br />
    } <br />
 <br />
    return $result; <br />
} <br />
``` <br />
 <br />
**See also:** [UUIDv7](https://www.perturb.org/display/1398_Perl_UUIDv7.html)
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1453/" />
		<title mode="escaped">Perl: Using Inline::C to embed C functions in your Perl scripts</title>
		<modified>2026-04-23T14:34:43-07:00</modified>
		<issued>2026-04-23T14:34:43-07:00</issued>
		<created>2026-04-23T14:34:43-07:00</created>
		<id>http://www.perturb.org/display/entry/1453/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

Perl allows "inline" code written in other languages. This is useful because you can have native C functions interact with your Perl code. By placing your C code in the `__DATA__` section of your Perl script you get clean separation between the two languages. <br />
 <br />
**Note:** `Inline::C` does not understand `uint64_t` in function definitions, so anything that interacts with Perl needs to use `UV` instead. Internally C functions can use and interact with `uint64_t` variables just fine. <br />
 <br />
```perl <br />
use strict; <br />
use warnings; <br />
use v5.16; <br />
use Inline 'C'; <br />
 <br />
############################################## <br />
 <br />
seed_splitmix64(time()); <br />
 <br />
for (1 .. 5) { <br />
    say splitmix64(); <br />
} <br />
 <br />
############################################## <br />
 <br />
__DATA__ <br />
__C__ <br />
 <br />
uint64_t x = 123456789; <br />
 <br />
void seed_splitmix64(UV seed) { <br />
    x = seed; <br />
} <br />
 <br />
UV splitmix64() { <br />
    uint64_t z = (x += 0x9e3779b97f4a7c15); <br />
    z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; <br />
    z = (z ^ (z >> 27)) * 0x94d049bb133111eb; <br />
 <br />
    return z ^ (z >> 31); <br />
} <br />
``` <br />
 <br />
This will compile the C code into a shared object in the `_Inline` directory in whichever directory you instantiated your Perl script. Code is only compiled once (and where there are changes), so your script performance will be very high.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1452/" />
		<title mode="escaped">Comparison of markup languages</title>
		<modified>2026-04-09T10:58:41-07:00</modified>
		<issued>2026-04-09T10:58:41-07:00</issued>
		<created>2026-04-09T10:58:41-07:00</created>
		<id>http://www.perturb.org/display/entry/1452/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

I've been investigating [JSON](https://www.json.org/) vs [YAML](https://yaml.org/) vs [TOML](https://toml.io/) for various applications. After testing many variations I ended up writing a [simple tool](https://www.perturb.org/code/js-serializer/) to compare all three live.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1451/" />
		<title mode="escaped">Linux: SFTP and SCP friendly login banners</title>
		<modified>2026-03-26T14:07:00-07:00</modified>
		<issued>2026-03-26T14:07:00-07:00</issued>
		<created>2026-03-26T14:07:00-07:00</created>
		<id>http://www.perturb.org/display/entry/1451/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

To display a message when a user logs into your server, add the following to `~/.bashrc`: <br />
 <br />
```bash <br />
# If it's an interactive terminal show the banner <br />
if [[ $- == *i* ]]; then <br />
    echo "Welcome to the monitoring server" <br />
    echo "Configuration is stored in /etc/myapp" <br />
fi <br />
``` <br />
 <br />
This runs _only_ for interactive sessions. Non-interactive connections such as SFTP and SCP remain unaffected, which prevents automated processes from breaking. <br />
 <br />
**See also:** The [text_color](https://github.com/scottchiefbaker/text_color) project.
]]>
		</content>
	</entry>
	<entry xmlns="http://purl.org/atom/ns#">
		<link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1450/" />
		<title mode="escaped">YAML is growing on me</title>
		<modified>2026-03-25T10:04:29-07:00</modified>
		<issued>2026-03-25T10:04:29-07:00</issued>
		<created>2026-03-25T10:04:29-07:00</created>
		<id>http://www.perturb.org/display/entry/1450/</id>
		<summary type="text/plain"></summary>
		<author>
			<name>Scott Baker</name>
			<url>http://www.perturb.org/</url>
			<email>scott@perturb.org</email>
		</author>
		<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
			<![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />

The more I learn about YAML, the more I like it. JSON is great as a machine readable format, but it sucks at being human readable. Want to add an element, better make sure you have **all** the commas and curly braces in the **exact** right place or the whole thing will be unusable. YAML on the other hand is designed to be human readable and modifiable. It's a very simple key/value system using indentation to represent layers.  <br />
 <br />
PHP has a [PECL module](https://bd808.com/pecl-file_formats-yaml/) with good YAML support. There are also pure PHP versions if you're unable to install PECL modules. [Symfony](https://github.com/symfony/yaml) provides one, and so does [Spyc](https://github.com/mustangostang/spyc). I prefer the latter because it's a single file and very easy to install. <br />
 <br />
On the Perl side there is [YAML::XS](https://metacpan.org/pod/YAML::XS), [YAML::PP](https://metacpan.org/pod/YAML::PP), and [many](https://metacpan.org/search?size=20&q=yaml) others.  <br />
 <br />
Parsing YAML is very easy in just about every language I can find. If you have a complex data structure that you need humans to interact with use YAML please. <br />
 <br />
Here is a [great breakdown](https://jsonlint.com/json-vs-yaml) of when to use YAML vs JSON: <br />
 <br />
| Use Case             | Recommended | Why                               | <br />
| -------------------- | ----------- | --------------------------------- | <br />
| API request/response | JSON        | Universal support, strict parsing | <br />
| Configuration files  | YAML        | Comments, readability             | <br />
| Browser/JavaScript   | JSON        | Native parsing                    | <br />
| Kubernetes/Docker    | YAML        | Industry standard                 | <br />
| Data interchange     | JSON        | Unambiguous, fast                 | <br />
| Human-edited files   | YAML        | Less punctuation                  | <br />
 <br />
[YAML spec](https://perlpunk.github.io/yaml-test-schema/schemas.html) differences.
]]>
		</content>
	</entry>
</feed>
