--- /dev/null
+USING: assocs kernel lru-cache sorting tools.test ;
+
+{
+ { { 3 3 } { 4 4 } { 5 5 } }
+} [
+ 3 <lru-hash>
+ 1 1 pick set-at
+ 2 2 pick set-at
+ 3 3 pick set-at
+ 4 4 pick set-at
+ 5 5 pick set-at
+ >alist natural-sort
+] unit-test
+
+{
+ { { 1 1 } { 4 4 } { 5 5 } }
+} [
+ 3 <lru-hash>
+ 1 1 pick set-at
+ 2 2 pick set-at
+ 3 3 pick set-at
+ 1 over at drop
+ 4 4 pick set-at
+ 5 5 pick set-at
+ >alist natural-sort
+] unit-test
+
+{
+ { { 2 2 } { 4 4 } { 5 5 } }
+} [
+ 3 <lru-hash>
+ 1 1 pick set-at
+ 2 2 pick set-at
+ 3 3 pick set-at
+ 1 over delete-at
+ 1 over at drop
+ 2 over at drop
+ 4 4 pick set-at
+ 5 5 pick set-at
+ >alist natural-sort
+] unit-test
--- /dev/null
+! Copyright (C) 2017 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors assocs deques dlists fry kernel linked-assocs
+linked-assocs.private math sequences.private ;
+
+IN: lru-cache
+
+TUPLE: lru-cache < linked-assoc max-size ;
+
+: <lru-cache> ( max-size exemplar -- assoc )
+ 0 swap new-assoc <dlist> rot lru-cache boa ;
+
+: <lru-hash> ( max-size -- assoc )
+ H{ } <lru-cache> ;
+
+M: lru-cache at*
+ [ assoc>> at* ] [ dlist>> dup ] bi '[
+ [
+ [ _ delete-node ]
+ [ _ push-node-back ]
+ [ obj>> second-unsafe ] tri
+ ] when
+ ] keep ;
+
+M: lru-cache set-at
+ [ call-next-method ] keep dup max-size>> [
+ over assoc>> assoc-size < [
+ [ dlist>> pop-front first-unsafe ]
+ [ assoc>> ]
+ [ dlist>> ] tri (delete-at)
+ ] [ drop ] if
+ ] [ drop ] if* ;