Profiles / Programming
MD

MQL developer

Atom lists, data types, constants, translations, session variables and error patterns.

10 recipes on this page · open in the interactive view

Recipes
  1. Clean a list of tags with atom functions
  2. Catalogue of math and physics constants with eval
  3. Add a language and translate the messages of an application
  4. Request context in session and environment variables
  5. Run user formulas safely: eval, try and error codes
  6. User rights as a bitmask
  7. Breadcrumb links from a page path
  8. Sort CSV columns: text sort versus numeric sorts
  9. Stable A/B test buckets from a hash
  10. Cache a slow result in a node with a TTL
executed on MentDB

Clean a list of tags with atom functions

Users typed tags with spaces, duplicates and padding. The script trims every atom, removes the duplicates, counts and finds a tag with and without trimming, and gives the first and last clean tags: the differences between the plain and the _lrtrim variants show at once.

Pipeline
Script
admin
#1. Tags typed by users;
-> "[tags]" " java, mql ,sql,mql, java ,json,mql";
#2. Clean and deduplicate;
-> "[trimmed]" (atom lrtrim [tags] ",");
-> "[unique]" (atom distinct_lrtrim [tags] ",");
#3. Count and find, raw atoms versus trimmed atoms;
-> "[cnt]" (concat (atom count [tags] "mql" ",") " raw, " (atom count_lrtrim [tags] "mql" ",") " trimmed");
-> "[dist]" (concat (atom count_distinct [tags] "mql" ",") " raw, " (atom count_lrtrim_distinct [tags] "mql" ","));
-> "[pos]" (concat (atom find [tags] "mql" ",") " raw, " (atom find_lrtrim [tags] "mql" ",") " trimmed, position " (atom position [tags] "mql" ",") "/" (atom position_lrtrim [tags] "mql" ","));
#4. Ends of the list and display;
concat "trimmed: " [trimmed] [_n_] "unique: " [unique] " = " (atom size [unique] ",") " tags" [_n_] "display: " (atom distinct_lrtrim_1sbefore [tags] ",") [_n_] "distinct raw: " (atom distinct [tags] ",") [_n_] "count mql: " [cnt] ", distinct count: " [dist] [_n_] "find mql: " [pos] [_n_] "first: " (atom get_first_lrtrim [tags] ",") ", last: " (atom get_last_lrtrim [tags] ",") ", second: " (atom get_lrtrim [tags] 2 ",");
Result
mentdb
trimmed: java,mql,sql,mql,java,json,mql
unique: java,mql,sql,json = 4 tags
display: java, mql, sql, json
distinct raw:  java, mql ,sql,mql, java ,json
count mql: 2 raw, 3 trimmed, distinct count: 1 raw, 1
find mql: 4 raw, 2 trimmed, position 4/2
first: java, last: mql, second: mql
Go further
  • Lowercase first with string lower so that MQL and mql are the same tag
  • Loop over the unique tags with for and atom get
executed on MentDB

Catalogue of math and physics constants with eval

A library needs a table of the 37 built-in constants with their value, uncertainty and unit. The script builds the command name of each constant, runs it with eval, splits the answer with atom functions and computes the relative uncertainty.

Pipeline
Script
admin
#1. Constants to document;
-> "[names]" "math_pi,math_two_pi,math_half_pi,math_four_pi,math_pi_square,physics_c,physics_c_square,physics_planck,physics_planck_over_two_pi,physics_e,physics_k,physics_n,physics_r,physics_f,physics_g,physics_g0,physics_newtonian_g,physics_m_electron,physics_m_proton,physics_m_neutron,physics_m_muon,physics_m_deuteron,physics_amu,physics_mp,physics_lp,physics_tp,physics_a0,physics_rinf,physics_eh,physics_fine_structure,physics_bohr_magneton,physics_nuclear_magneton,physics_magn_flux_quantum,physics_perm_vac_electric,physics_perm_vac_magnetic,physics_z0,physics_stefan_boltzmann";
-> "[out]" "";
-> "[n]" (atom size [names] ",");
for (-> "[i]" 1) (<= [i] [n]) (++ "[i]") {
	-> "[nm]" (atom get [names] [i] ",");
	#2. eval runs a command built as a string;
	-> "[raw]" (string trim (eval (concat "constant " [nm] ";")));
	#3. Exact constants have no parenthesis;
	if (string starts_with [raw] "(") {
		-> "[inner]" (string regexp_extract [raw] "^\(([^)]*)\)" 1);
		-> "[val]" (atom get [inner] 1 " ");
		-> "[rel]" (concat "rel. " (/ (atom get [inner] 3 " ") [val]));
		-> "[unit]" (string trim (string regexp_extract [raw] "^\([^)]*\)(.*)$" 1));
	} {
		-> "[val]" (atom get_first [raw] " ");
		-> "[rel]" "exact";
		-> "[unit]" (atom get_last [raw] " ");
	};
	#4. Two constants per line;
	-> "[sep]" (case (== [i] [n]) {"";} (== (math mod [i] 2) 0) {[_n_];} {" | ";});
	-> "[out]" (concat [out] [nm] " = " [val] (if (is empty [unit]) {"";} {concat " " [unit];}) " (" [rel] ")" [sep]);
};
[out];
Result
mentdb
math_pi = 3.1415926535897931 (rel. 7.002817496043395E-17) | math_two_pi = 6.2831853071795862 (rel. 7.002817496043395E-17)
math_half_pi = 1.5707963267948966 (rel. 7.002817496043395E-17) | math_four_pi = 12.5663706143591725 (rel. 7.082394967589343E-17)
math_pi_square = 9.869604401089358 (rel. 9.017585344168063E-17) | physics_c = 299792458 m/s (exact)
physics_c_square = 89875517873681764 m²/s² (exact) | physics_planck = 6.626069E-34 J·s (rel. 1.6601094857297744E-7)
physics_planck_over_two_pi = 1.0545717E-34 J·s (rel. 1.7068540716577167E-7) | physics_e = 1.6021765E-19 C (rel. 8.73811343506786E-8)
physics_k = 1.380651E-23 J/K (rel. 1.7383104057433776E-6) | physics_n = 6.022142E23 1/mol (rel. 1.6605387252575578E-7)
physics_r = 8.31447 J/(mol·K) (rel. 1.9243559721786233E-6) | physics_f = 96485.34 C/mol (rel. 2.4874245144391884E-7)
physics_g = 9.8066499999999976 m/s² (rel. 9.075474295503565E-17) | physics_g0 = 0.00007748092 S (rel. 3.3556648527147077E-7)
physics_newtonian_g = 6.674E-11 m³/(kg·s²) (rel. 1.4983518130056938E-4) | physics_m_electron = 9.109383E-31 kg (rel. 1.7564307044725203E-7)
physics_m_proton = 1.6726217E-27 kg (rel. 1.7338050797738665E-7) | physics_m_neutron = 1.6749273E-27 kg (rel. 1.731418432310465E-7)
physics_m_muon = 1.8835314E-28 kg (rel. 1.752028131837887E-7) | physics_m_deuteron = 3.3435833E-27 kg (rel. 1.7047578865464484E-7)
physics_amu = 1.6605389E-27 kg (rel. 1.6861995825572048E-7) | physics_mp = 2.1765E-8 kg (rel. 7.351252010107971E-5)
physics_lp = 1.6162E-35 m (rel. 7.424823660438064E-5) | physics_tp = 5.3912E-44 s (rel. 7.60498590295296E-5)
physics_a0 = 5.291772E-11 m (rel. 3.4015070944099634E-7) | physics_rinf = 1.097373156852E7 1/m (rel. 6.652249469033196E-12)
physics_eh = 4.3597442E-18 J (rel. 1.6514730382576115E-7) | physics_fine_structure = 0.007297353 (rel. 3.4258997748909776E-7)
physics_bohr_magneton = 9.274009E-24 C·J·s/kg (rel. 4.313129305783508E-7) | physics_nuclear_magneton = 5.050783E-27 C·J·s/kg (rel. 4.355760285088471E-7)
physics_magn_flux_quantum = 2.0678337E-15 Wb (rel. 2.5147089923140336E-7) | physics_perm_vac_electric = 8.854187817620389E-12 A²·s²/(N·m²) (rel. 2.7105817602195534E-16)
physics_perm_vac_magnetic = 0.0000012566370614359171 N/A² (rel. 8.753521870054245E-17) | physics_z0 = 376.73031346177061 Ω (rel. 7.432372442426604E-17)
physics_stefan_boltzmann = 5.6704E-8 J/(K^4·s·m²) (rel. 7.406884875846501E-6)
Go further
  • Store the table in a JSON array with json iarray to serve it from a web service
  • Use the constants directly in math calc with _c, _h, _k...
needs your systems

Add a language and translate the messages of an application

An application goes German. The script creates and activates the language if needed, stores the same message in three languages, refreshes the cache, reads the German text, and shows how to remove the key and the language later. It writes to the server, so it is not run here.

Pipeline
Script
admin
#1. Create the language once;
if (not (translate exist_language de)) {
	translate add_language de "Deutsch";
};
translate active_language de true;
#2. The same key in three languages;
translate set "cart.empty" en "Your cart is empty.";
translate set "cart.empty" fr "Votre panier est vide.";
translate set "cart.empty" de "Ihr Warenkorb ist leer.";
#3. Refresh the cache and read the German text;
translate reset_cache;
-> "[msg]" (translate get "cart.empty" de);
log trace (concat "cache: " (translate stat_cache));
#4. Later, to remove the key then the language;
translate delete "cart.empty";
translate delete_language de;
[msg];
Result
This recipe uses your own connections (database, SFTP, SMTP...). Create them with the CM functions, then run it on your server.
Go further
  • Pick the language of the user from a session variable, see the next recipe
  • Deactivate a language without deleting it: translate active_language de false
executed on MentDB

Request context in session and environment variables

A script needs to know who runs it and to carry a small context (language, counters, a greeting) between steps. It reads the user and the session, sets, increments, decrements, concatenates, tests and deletes environment variables, and translates the greeting with a fallback to English.

Pipeline
Script
admin
#1. Who runs the code, in which session;
-> "[user]" (who);
-> "[session]" (sid);
-> "[open]" (count sessions);
#2. A context kept in the environment;
env set var "[lang]" "fr";
env set var "[calls]" 10;
env incr var "[calls]" 5;
env decr var "[calls]" 2;
#3. Translation with a fallback to English;
if (not (translate exist_language (env get var "[lang]"))) {env set var "[lang]" "en";};
concat_var "[greeting]" (translate get "hello" (env get var "[lang]")) " " [user] ", " (env get var "[calls]") " calls";
#4. Delete a variable and show what is left;
-> "[tmp]" "scratch";
env del var "[tmp]";
concat [greeting] [_n_] "session " [session] " among " [open] " open, temp deleted: " (not (env exist var "[tmp]")) [_n_] "commands run by this user: " (cmdid) [_n_] (env show);
Result
mentdb
hello admin, 13 calls
session 265 among 3 open, temp deleted: 1
commands run by this user: 2
{
  "[CLIENT_HOST_NAME]": "localhost",
  "[session]": "265",
  "[open]": "3",
  "[calls]": "13",
  "[greeting]": "hello admin, 13 calls",
  "[CLIENT_HOST_ADDRESS]": "127.0.0.1",
  "[user]": "admin",
  "[CLIENT_PORT]": "59851",
  "[lang]": "fr"
}
Go further
  • -> "[x]" 1 and env set var "[x]" 1 do the same: the arrow is the short form
  • execute starts a script in a new environment, call and include share yours
executed on MentDB

Run user formulas safely: eval, try and error codes

A tool lets users type small MQL formulas. The script runs each one with eval inside try, raises a coded exception for a forbidden word, routes the error with switch, counts the errors in a synchronized block and builds a JSON report of the results and errors.

Pipeline
Script
admin
#1. Formulas typed by users, separated by |;
-> "[formulas]" "+ 2 3;|* 4 (+ 1 1);|unknown_fx 3;|script show ghost;|bd/ 10 4;";
json load "rx_eval" "[]";
-> "[errors]" 0;
for (-> "[i]" 1) (<= [i] (atom size [formulas] "|")) (++ "[i]") {
	-> "[f]" (atom get [formulas] [i] "|");
	try {
		#2. Refuse some words with a coded exception;
		if (string contains [f] "script ") {exception (403) ("script functions are not allowed");};
		-> "[r]" (eval [f]);
		json iarray "rx_eval" "/" (concat "{\"mql\": \"" (string json_escape [f]) "\", \"result\": \"" [r] "\"}") OBJ;
	} {
		#3. Route the error by its code;
		-> "[code]" (string regexp_extract [err] "([0-9]+): [^\n]*$" 1);
		-> "[why]" (switch ([code]) ("403") {"forbidden"} {"invalid MQL"});
		synchronized ("rx_eval_errors") {++ "[errors]";};
		json iarray "rx_eval" "/" (concat "{\"mql\": \"" (string json_escape [f]) "\", \"error\": \"" [why] "\"}") OBJ;
	} "[err]";
};
#4. Keep the report, free the memory;
-> "[report]" (json doc "rx_eval");
json unload "rx_eval";
concat [errors] " errors" [_n_] [report];
Result
mentdb
2 errors
[
  {
    "result": "5",
    "mql": "+ 2 3;"
  },
  {
    "result": "8",
    "mql": "* 4 (+ 1 1);"
  },
  {
    "mql": "unknown_fx 3;",
    "error": "invalid MQL"
  },
  {
    "mql": "script show ghost;",
    "error": "forbidden"
  },
  {
    "result": "2.5",
    "mql": "bd/ 10 4;"
  }
]
Go further
  • synchronized lets only one session at a time run the block of a key: use it around shared counters
  • Run several independent formulas at the same time with parallel
executed on MentDB

User rights as a bitmask

An application stores the rights of a role in one integer, one bit per right. The script grants rights with OR, toggles them with XOR, decodes a mask with AND in a loop, and answers the two checks the services ask: can delete, is admin.

Pipeline
Script
admin
#1. Rights of an application stored as bits in one integer;
-> "[names]" "read,write,delete,export,admin";
-> "[READ]" 1;
-> "[WRITE]" 2;
-> "[DELETE]" 4;
-> "[EXPORT]" 8;
-> "[ADMIN]" 16;
#2. Grant rights with OR: an editor reads, writes and exports;
-> "[editor]" (math bit_or (math bit_or [READ] [WRITE]) [EXPORT]);
#3. Toggle a right with XOR: export removed, delete added;
-> "[revoked]" (math bit_xor [editor] [EXPORT]);
-> "[mod]" (math bit_or [revoked] [DELETE]);
#4. Decode a mask: AND with each bit, the bit value is 2 power position;
-> "[decode]" "";
for (-> "[i]" 1) (<= [i] (atom size [names] ",")) (++ "[i]") {
	-> "[bit]" (math power 2 (- [i] 1));
	if (!= (math bit_and [mod] [bit]) 0) {
		-> "[decode]" (concat [decode] (atom get [names] [i] ",") " ");
	};
};
#5. Checks used by the services;
-> "[can_delete]" (== (math bit_and [mod] [DELETE]) [DELETE]);
-> "[is_admin]" (== (math bit_and [mod] [ADMIN]) [ADMIN]);
concat "editor = " [editor] " = " (string lpad (string bin [editor]) "0" 5) [_n_] "export revoked = " [revoked] " = " (string lpad (string bin [revoked]) "0" 5) [_n_] "moderator = " [mod] " = " (string lpad (string bin [mod]) "0" 5) " = " (string trim [decode]) [_n_] "can delete: " [can_delete] ", is admin: " [is_admin] ", rights in common with the editor: " (string bin (math bit_and [mod] [editor]));
Result
mentdb
editor = 11 = 01011
export revoked = 3 = 00011
moderator = 7 = 00111 = read write delete
can delete: 1, is admin: 0, rights in common with the editor: 11
Go further
  • Store the mask in a column of the user table: one INT holds up to 31 rights.
  • string lpad (string bin [mask]) "0" 8 prints the mask on a fixed width for a log line.
executed on MentDB

Breadcrumb links from a page path

Build the HTML breadcrumb of a shop page from its path. Each level links to the path up to itself, built with atom before_includ and slugs; the current page is not a link and its label is cut; the back button goes to the parent.

Pipeline
Script
admin
#1. The path of the page asked by the visitor;
-> "[path]" "Home/Shop/Books/Science Fiction/Dune: Deluxe Edition";
-> "[n]" (atom size [path] "/");
-> "[crumbs]" "";
#2. Each crumb links to the path up to its own level, level included;
for (-> "[i]" 1) (<= [i] [n]) (++ "[i]") {
	-> "[label]" (atom get [path] [i] "/");
	-> "[upto]" (atom before_includ [path] [i] "/");
	-> "[url]" "";
	for (-> "[j]" 2) (<= [j] [i]) (++ "[j]") {
		-> "[url]" (concat [url] "/" (string slugify (atom get [upto] [j] "/")));
	};
	if (is empty [url]) {-> "[url]" "/";};
	#3. The last level is the current page: no link;
	if (== [i] [n]) {
		-> "[crumbs]" (concat [crumbs] "<li class=\"active\">" (string html_escape (string truncate [label] 18)) "</li>");
	} {
		-> "[crumbs]" (concat [crumbs] "<li><a href=\"" [url] "\">" (string html_escape [label]) "</a></li>" [_n_]);
	};
};
#4. The parent page and the depth for the back button;
concat "<ol class=\"breadcrumb\">" [_n_] [crumbs] [_n_] "</ol>" [_n_] "back to: " (atom get_last (atom before_exclud [path] [n] "/") "/") ", depth " (- [n] 1);
Result
mentdb
<ol class="breadcrumb">
<li><a href="/">Home</a></li>
<li><a href="/shop">Shop</a></li>
<li><a href="/shop/books">Books</a></li>
<li><a href="/shop/books/science-fiction">Science Fiction</a></li>
<li class="active">Dune: Deluxe Ed...</li>
</ol>
back to: Science Fiction, depth 4
Go further
  • Return the crumbs as JSON for a single-page app instead of HTML, with json iarray.
  • Add the schema.org BreadcrumbList attributes for the search engines.
executed on MentDB

Sort CSV columns: text sort versus numeric sorts

Columns of a CSV export arrive as text. A text sort puts invoice 1001 before 98; the script sorts each column with the numeric sort of its type (int, long epochs, double amounts, float rates), finds the duplicated invoice and the period covered.

Pipeline
Script
admin
#1. Columns of an export, read as text from a CSV file;
-> "[invoices]" "1002,98,1001,250,98,1100,7";
-> "[amounts]" "19.9,120,5.25,1200.5,99.99";
-> "[epochs]" "1793520000000,1761984000000,1793433600000";
-> "[rates]" "0.2,0.055,0.1,0.021";
#2. A text sort compares character by character: 1001 comes before 98;
-> "[as_text]" (string order (concat "[\"" (string replace [invoices] "," "\",\"") "\"]"));
#3. Numeric sorts by type: int, long for epoch ms, double, float;
-> "[as_int]" (math order_int (concat "[" [invoices] "]"));
-> "[as_long]" (math order_long (concat "[" [epochs] "]"));
-> "[as_double]" (math order_double (concat "[" [amounts] "]"));
-> "[as_float]" (math order_float (concat "[" [rates] "]"));
#4. Duplicates: the most frequent invoice number and the unique list;
-> "[dup]" (stat mode (concat "[" [invoices] "]"));
-> "[unique]" (atom distinct [invoices] ",");
#5. Oldest and newest dates from the sorted epochs;
json load "rx_p4l_ep" [as_long];
-> "[oldest]" (date long_to_ts (json select "rx_p4l_ep" "/[0]"));
-> "[newest]" (date long_to_ts (json select "rx_p4l_ep" (concat "/[" (- (json count "rx_p4l_ep" "/") 1) "]")));
json unload "rx_p4l_ep";
concat "text sort:   " [as_text] [_n_] "int sort:    " [as_int] [_n_] "long sort:   " [as_long] [_n_] "double sort: " [as_double] [_n_] "float sort:  " [as_float] [_n_] "duplicate invoice: " [dup] ", unique: " [unique] " (" (atom size [unique] ",") " of " (atom size [invoices] ",") ")" [_n_] "period: " [oldest] " to " [newest];
Result
mentdb
text sort:   ["1001","1002","1100","250","7","98","98"]
int sort:    [7,98,98,250,1001,1002,1100]
long sort:   [1761984000000,1793433600000,1793520000000]
double sort: [5.25,19.9,99.99,120.0,1200.5]
float sort:  [0.021,0.055,0.1,0.2]
duplicate invoice: [98], unique: 1002,98,1001,250,1100,7 (6 of 7)
period: 2025-11-01 12:00:00 to 2026-11-01 12:00:00
Go further
executed on MentDB

Stable A/B test buckets from a hash

Split the users of a checkout test into control (10 %), A and B (45 % each) without storing anything: the SHA-256 of the test name and the user id gives a slot from 0 to 99, so a user always lands in the same bucket.

Pipeline
Script
admin
#1. An A/B test on the checkout page: 10 percent control, 45 A, 45 B;
-> "[test]" "checkout-2026-11";
-> "[users]" "u1001,u1002,u1003,u1004,u1005,u1006,u1007,u1008,u1009,u1010,u1011,u1012";
json load "rx_p4l_ab" "{\"control\": [], \"A\": [], \"B\": []}";
-> "[n]" (atom size [users] ",");
for (-> "[i]" 1) (<= [i] [n]) (++ "[i]") {
	-> "[u]" (atom get [users] [i] ",");
	#2. Same user and same test always give the same hash, so the same bucket;
	-> "[h]" (string hex_to_int (string left (string sha_256 (concat [test] ":" [u])) 6));
	-> "[slot]" (math mod [h] 100);
	-> "[bucket]" (case (< [slot] 10) {"control"} (< [slot] 55) {"A"} {"B"});
	json iarray "rx_p4l_ab" (concat "/" [bucket]) (concat [u] ":" [slot]) STR;
};
#3. Check that a user keeps the bucket at the next visit;
-> "[again]" (math mod (string hex_to_int (string left (string sha_256 (concat [test] ":u1005")) 6)) 100);
#4. Sizes of the buckets and the members;
-> "[out]" (concat "control " (json count "rx_p4l_ab" "/control") ", A " (json count "rx_p4l_ab" "/A") ", B " (json count "rx_p4l_ab" "/B") " of " [n] " users" [_n_] "u1005 slot at the next visit: " [again] [_n_] (string replace (string replace (json doc "rx_p4l_ab") [_n_] "") "  " ""));
json unload "rx_p4l_ab";
[out];
Result
mentdb
control 1, A 5, B 6 of 12 users
u1005 slot at the next visit: 57
{"A": ["u1001:20","u1004:38","u1006:38","u1007:21","u1008:11"],"B": ["u1002:93","u1003:77","u1005:57","u1009:88","u1010:78","u1012:69"],"control": ["u1011:5"]}
Go further
  • Change the test name and the users are shuffled again: buckets of two tests are independent.
  • Log the bucket with log write at each order to compare the conversion of A and B later with stat ttest.
executed on MentDB

Cache a slow result in a node with a TTL

A slow computation (counting primes) is cached in a server node with its timestamp. The first call computes and stores it, the second reads the fresh value from the node; the cache is then invalidated.

Pipeline
Script
admin
#1. A slow computation: count the primes below a limit;
-> "[limit]" 3000;
-> "[key]" (concat "tuto_p4l_cache_primes_" [limit]);
-> "[ttl_s]" 60;
-> "[log]" "";
#2. Cache-aside: read the node if it is fresh, else compute and store it;
for (-> "[call]" 1) (<= [call] 2) (++ "[call]") {
	-> "[t0]" (date current_ms);
	-> "[hit]" 0;
	if (node exist [key]) {
		-> "[age_s]" (/ (- (date current_ms) (node select [key] "/stored_ms")) 1000);
		if (< [age_s] [ttl_s]) {-> "[hit]" 1;};
	};
	if (== [hit] 1) {
		-> "[primes]" (node select [key] "/value");
	} {
		-> "[primes]" 0;
		for (-> "[x]" 2) (< [x] [limit]) (++ "[x]") {
			-> "[p]" 1;
			for (-> "[d]" 2) (and [p] (<= (* [d] [d]) [x])) (++ "[d]") {
				if (== (math mod [x] [d]) 0) {-> "[p]" 0;};
			};
			-> "[primes]" (+ [primes] [p]);
		};
		if (node exist [key]) {node delete [key];};
		node create [key];
		node iobject [key] "/" "value" [primes] INT;
		node iobject [key] "/" "stored_ms" (date current_ms) NUM;
		node iobject [key] "/" "stored_at" (date now) STR;
	};
	-> "[log]" (concat [log] "call " [call] ": " [primes] " primes, " (if (== [hit] 1) {"cache hit"} {"computed"}) ", " (- (date current_ms) [t0]) " ms" [_n_]);
};
#3. What the cache node holds, then invalidate it;
-> "[fields]" (string replace (string replace (node fields [key] "/") [_n_] "") " " "");
node delete [key];
concat [log] "node fields: " [fields] [_n_] "after invalidation, cached: " (node exist [key]);
Result
mentdb
call 1: 430 primes, computed, 75 ms
call 2: 430 primes, cache hit, 0 ms
node fields: ["stored_ms","value","key","stored_at"]
after invalidation, cached: 0
Go further
  • Nodes persist on the server: other sessions and other scripts read the same cache.
  • Wrap the write in synchronized ("cache_primes") {...} when several threads may compute it at the same time.

Also in Programming

MB
MQL beginner
Variables, operators, if, loops and your first try/exception: learn MQL step by step.
10 recipes
BW
Backend & web service developer
Typed scripts, execute / call / include, generated calls and URLs, parameters and logs.
10 recipes
DT
Date & time developer
Calendars, business days, time zones, ISO and epoch, durations, quarters and week numbers.
10 recipes
SE
String & encoding developer
Cleaning, case styles, regex, URL/HTML/Base64 encodings, number bases and encryption.
10 recipes
DV
Data validation developer
IBAN, BIC, SIRET, Luhn, email, IP, UUID, JSON and date checks gathered in a validation report.
10 recipes
JD
JSON & document store developer
In-memory JSON documents, persistent nodes and sequences: build, walk, sort, clean up.
10 recipes
SD
Script developer
Full script lifecycle in the MQL editor: typed parameters, read back, generate, patch, deploy, copy, grant, delete.
10 recipes
EM
Execution modes
execute, call, include, sub_include, parallel, stack: which environment, which checks, which logs.
11 recipes
WS
Web service developer
A small REST resource with get, post, put and delete scripts: validation, JSON answers, codes, grants, URLs and API docs.
10 recipes
AD
Async developer
Asynchronous processing with the stack: push runs now or later, priorities and parallel limits, errors and replays, flows and cleanup.
10 recipes
SD
Scheduler developer
Cron jobs and delayed runs: add, resume, pause, update and remove jobs, prove they ran, and postpone stack runs with a delay condition.
10 recipes
ED
Event developer
Event-driven scripts: file watchers that push each file event to the stack, validation, archiving, errors and safe restarts.
10 recipes
CC
Configuration & connections
Parameters (private, described, locked, deployed), environment variables, sessions and connections used by your scripts.
12 recipes
VD
Versioning & deployment
Group your scripts, commit, compare, roll back, export, import and package a release.
10 recipes
DE
Debugging & error handling
Coded errors with try/exception, logs with correlation ids, timing, metrics and defensive checks.
10 recipes
SD
SQL developer in MQL
Connections, DDL and DML with sql encode, transactions, cursors, parse, and exports to JSON, CSV, Excel and PDF on a real local database. Run the recipes in order: the first one creates the tuto_db_h2 database.
10 recipes
CD
CRUD & data API developer
Generate SCRUD scripts from a table, patch and install them, write typed read and write APIs, check data quality and manage connections per environment. Uses the tuto_db_h2 database of the SQL developer recipes; the last recipe removes it.
10 recipes
WA
Web application developer
Create a web app, its host name, pages, ajax forms, menu and grants, then remove it all.
10 recipes
AI
Algorithms in MQL
Sorting, searching, recursion, data structures and number algorithms: MQL is a real programming language.
10 recipes
CF
Control flow
if, if force, case, switch, mode, for, while, repeat, break, continue, parallel and synchronized on real cases.
10 recipes
TM
The MQL language in depth
Data types and null, booleans, comments, variables and scope, eval and mql blocks, coded errors and try.
10 recipes
SU
Screen & UI developer (sajax)
Build the screens of MentDB web apps in MQL: Bootstrap grids, forms and every control, ajax buttons, alerts, refreshes and charts.
10 recipes