! -*- factor -*- ! vim:set ft=factor: ! @@PLEAC@@_NAME ! @@SKIP@@ Factor ! @@PLEAC@@_WEB ! @@SKIP@@ http://factorcode.org/ ! @@PLEAC@@_INTRO ! @@SKIP@@ Factor is a general purpose, dynamically typed, ! @@SKIP@@ stack-based programming language released under a BSD-style license. ! @@SKIP@@ Factor has variables (global and local) but most of the time it is more ! @@SKIP@@ idiomatic to put results on the stack. The examples will look different ! @@SKIP@@ from the typical "a = b(x)" of other programming languages. ! @@PLEAC@@_1.0 ! ----------------------------- : string ( -- str ) "\\n" ; ! two characters, \ and an n : string ( -- str ) "Jon 'Maddog' Orwant" ; ! literal single quotes ! ----------------------------- : string ( -- str ) "\n" ; ! a "newline" character : string ( -- str ) "Jon \"Maddog\" Orwant" ; ! literal double quotes ! ----------------------------- ! Multiline strings need the multiline vocabulary USE: multiline STRING: a This is a multiline document terminated by ; on a line by itself ; : a ( -- str ) <" This is a multiline document terminated by double quotes plus greater sign"> ; ! ----------------------------- ! @@PLEAC@@_1.1 ! ----------------------------- ! use subseq from the sequences vocabulary, since strings are just sequences from to str subseq 1 3 "abcdefg" subseq . ! "bc" ! The rest from a given position is handled by tail str n tail 1 "abcdefg" tail . ! "bcdefg" ! Replacing a substring with replace-slice newstr from to str replace-slice "1234" 3 7 "abcdefg" [ replace-slice ] keep . !"abc1234" : replace-tail ( new from seq -- ) dup length swap [ replace-slice ] keep ; "1234" 3 "abcdefg" replace-tail . ! "abc1234" ! ----------------------------- ! split at five character boundaries USE: splitting 5 group ! Splits sequence/string on top of stack into an array "abcdefghijklmnopqrstuvwxyz" 5 group . ! { "abcde" "fghij" "klmno" "pqrst" "uvwxy" "z" } ! chop string into individual characters 1 group "abcd" 1 group . ! { "a" "b" "c" "d" } ! ----------------------------- : str ( -- str ) "This is what you have" ; ! +012345678901234567890 Indexing forwards (left to right) ! 109876543210987654321- Indexing backwards (right to left) ! note that 0 means 10 or 20, etc. above 0 1 str subseq ! "T" (on top of stack) str 1 head ! "T" 5 7 str subseq ! "is" str 13 tail ! "you have" str 1 tail* ! "e" str 4 tail* ! "have" ! 8 indexed from backward, 3 characters str length 8 - dup 3 + str subseq ! "you" ! Or with a new word, using the locals vocabulary USE: locals :: chars-from-rindex ( from count str -- newstr ) str length from - dup count + str subseq ; 8 3 str chars-from-rindex ! "you" ! ----------------------------- SYMBOL: str "This is what you have" str set str get print ! This is what you have str get ! Top of stack: "This is what you have" [ 5 head ] [ 7 tail ] bi "wasn't" swap 3append ! change "is" to "wasn't" ! Top of stack: "This wasn't what you have" 13 head "ondrous" append ! replace last 12 characters ! Top of stack: "This wasn't wondrous" 1 tail ! delete first character ! Top of stack: "his wasn't wondrous" 10 head* ! delete last 10 characters ! Top of stack: "his wasn'" str set ! str = "his wasn'" str get print ! his wasn' ! ----------------------------- ! you can test substrings with "subseq?" 10 tail* "substring" swap subseq? [ "\"substring\" within the last 10 characters" print ] when ! substitute "at" for "is", restricted to first five characters USING: peg peg.search ; 5 cut >r "is" token [ drop "at" ] action replace r> append ! ----------------------------- ! exchange the first and last letters in a string "make a hat" 1 cut 1 cut* spin 3append print ! take a ham ! ----------------------------- ! @@PLEAC@@_1.3 ! ----------------------------- swap ! ----------------------------- ! @@PLEAC@@_1.15 ! ----------------------------- ! The "csv" vocabulary allows to parse real CSV ! reading the file "testdata.csv", UTF-8 encoded, CSV format USE: csv "testdata.csv" utf8 csv ! An array of row arrays is on the top of the stack now. ! ----------------------------- ! You could use the word "" to turn a string into a stream. USING: csv io.streams.string ; "XYZZY,\"\",\"O'Reilly, Inc\",\"Wall, Larry\",\"a \"\"glug\"\" bit,\",5,\"Error, Core Dumped\"" csv . ! { ! { ! "XYZZY" ! "" ! "O'Reilly, Inc" ! "Wall, Larry" ! "a \"glug\" bit," ! "5" ! "Error, Core Dumped" ! } ! } ! ----------------------------- ! @@PLEAC@@_3.0 ! ----------------------------- ! All examples use the "calendar" vocabulary USE: calendar [ "Today is day " % now day-of-year # " of the current year." % ] "" make print ! Today is day 132 of the current year. ! ----------------------------- ! @@PLEAC@@_3.1 ! ----------------------------- now ! puts timestamp on stack ! accessing day day>> ! ----------------------------- ! Formatting the date with "calender.format" vocabulary USE: calendar.format now timestamp>rfc3339 ! Top of stack: "2008-05-11T22:39:01+02:00" now timestamp>ymd ! Top of stack: "2008-05-11" ! ----------------------------- ! @@PLEAC@@_3.2 ! ----------------------------- ! Epoch milliseconds now timestamp>millis ! Top of stack: 1210538827773 ! Calculate seconds 1000 / >integer ! ----------------------------- ! GMT milliseconds gmt timestamp>millis ! Top of Stack: 1210539018199 ! @@PLEAC@@_3.3 ! ----------------------------- ! Epoch milliseconds to timestamp 1210538827773 millis>timestamp ! @@PLEAC@@_3.4 ! ----------------------------- ! Durations can be added and substracted with the words "time+" and "time-" now 5 days time+ timestamp>ymd print ! 2008-05-17 now 5 days time- timestamp>ymd print ! 2008-05-07 ! ----------------------------- 1973 1 18 3 45 50 gmt-offset-duration ! Birthtime 0 0 55 2 17 5 ! Interval time+ timestamp>string "Then is " swap append print ! Then is Wed, 14 Mar 1973 06:02:55 ! ----------------------------- "Nat was 55 days old on: " 1973 1 18 55 days time+ timestamp>ymd append print ! Nat was 55 days old on: 1973-03-14 ! ----------------------------- ! @@PLEAC@@_3.5 ! ----------------------------- ! Timestamps can be substracted from each other with "time-". You get a duration, ! which can be converted to the number of seconds, minutes, etc. now 5 days time- ! 5 days before now 5 days time+ ! in 5 days time- ! substracting the two timestamps dt>days . ! converting duration to number of days and prettyprinting it. ! -10 ! ----------------------------- ! Putting duration since lunar landing onto the stack: now 1969 7 20 20 17 40 instant ! 1969-07-20 20:17:40 UTC time- ! ----------------------------- USING: calendar math.parser ; 1981 6 16 4 35 25 instant ! 16 Jun 1981, 4:35:25 UTC, Bree 1973 1 18 3 45 50 instant ! 18 Jan 1973, 3:45:50 UTC, Nat time- dt>seconds dup ! Duplicates top of stack so we can use it later again. [ "There were " % # " seconds between Nat and Bree" % ] "" make print ! There were 265337375 seconds between Nat and Bree [ dup 60 mod dup , ! seconds - 60 / ! rest in minutes dup 60 mod dup , ! minutes - 60 / ! rest in hours dup 24 mod dup , ! hours - 24 / ! rest in days dup 7 mod dup , ! days - 7 / , ! weeks ] { } make [ [ "(" % # " weeks, " % # " days, " % # ":" % # ":" % # ")" % ] "" make ] with-datastack first print ! (438 weeks, 5 days, 0:49:35) ! ----------------------------- 1981 6 16 ! 16 Jun 1981, Bree 1973 1 18 ! 18 Jan 1973, Nat time- dt>days [ "There were " % # " days between Nat and Bree" % ] "" make print ! There were 3071 days between Nat and Bree ! -----------------------------