Documentation
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.gitignore
FEATURES.md
LICENSE
README.md

README.md

Lice Reference

Language design

  • Strict syntax
  • Lisp-style comments
(233) ; 233

233 ; 233

(type 233) ; 233 is a java.lang.Integer

; assignment
(-> fucker 233) ; OK

; immediate value
fucker ; 233
  • Variables
|> 12903
12903 => java.lang.Integer

|> (-> fuck 9320)
9320 => java.lang.Integer

|> fuck
9320 => java.lang.Integer
  • Basic functions
(+ 2 3 4 (* 2 5)) ; result: 19

(sqrt 100) ; result: 10.0

; also '||'
(&& (> 3 2 1) (>= 3 3 1)) ; result: true

(print 1) ; 1
(type 1) ; java.lang.Integer

; same as Java "String.format"
(format "%d %d" 233 233)
  • Compare
(== 1 1) ; number comparison,
         ; is actually "1 == 1"
(== 1 1N) ; true
(== 1 (->double 1)) ; true
(=== a b) ; is actually a.equals(b)
(=== 1 1N) ; false

; also != !==
  • Literals
() ; null
null ; null
true ; true
false ; false
10 ; 10
0o10 ; 8
0x10 : 16
0b10 ; 2
233N ; BigInteger("233")
"deep" ; "deep"
  • Primitives
|> (- 1N 10)
-9 => java.math.BigInteger

|> (- 10N 1)
9 => java.math.BigInteger

|> (+ 1 1)
2 => java.lang.Integer

|> (+ 9999999999999999999999999999999999999N 9999999999)
10000000000000000000000000009999999998 => java.math.BigInteger

|> (- 9999999999999999999999999999999999999N 9999999999)
9999999999999999999999999990000000000 => java.math.BigInteger

|> (+ 1 1)
2 => java.lang.Integer

|> (+ 1 1.0)
2.0 => java.lang.Float

|> (+ 1 1.1287391873917392379372193792137198237189237291)
2.128739187391739 => java.lang.Double
  • File/URL APIs
(if (! (file-exists? "save"))
    (|> (write-file (file "save") "0")
         (print "no no no"))
    (println "yes yes yes"))

(print (read-url (url "http://ice1000.tech")))

(print (read-file (file "src/lice/core/SymbolList.kt")))

(write-file (file "output")
            (str-con "deep " "dark" "fantasy"))
  • Casts
(str->int "12345678") ; dicimal
(str->int "0xFFF") ; hex
(str->int "0o2333") ; octal
(str->int "0b10100101") ; binary

(int->hex 12345678) ; result: 0xbc614e
(int->oct 12345678) ; result: 057060516
(int->bin 12345678) ; result: 0b101111000110000101001110

(->str (file "deep")) ; result: "deep"
  • if is function, too

It's lazily evaluated.

(print (if (>= 1 2)
    (read-file (file "out")) ; will not be read
    (read-file (file "in"))))
  • A global variable map to store values
(-> var "actual") ; put "actual" into "var"

(print var) ; prints "actual"
  • Loop
(-> i 0)
(while (> 10 i)
       (|> (print i)
           (-> i (+ 1 i))))
(undef i)
; |> means to evaluate every parameters given
; just like 'run' in clojure, 'begin' in scheme
; this prints from 0 to 9

Functional Programming

  • Functions are first-class:
((if true + -) 11 11)
; 22
; I'll show you the procedure:
;
; ((if true + -) 11 11)
; (+ 11 11)
; 22

(+)
; 0

(-)
; 0

(*)
; 1

call-by-what?

  • Rules

the def-family functions defines functions.

; rule
(def[xxx] function-name [parameters1, parameters2, ..] function body)

; example
(def gcd a b (if (== 0 b) a (gcd b (% a b))))
;^^^ ^^^ ^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
; |   |  | |                |
; |   |  | |         function body
; |   | parameters
; | the name of the function
;the key word
  • Call by value (the mostly used)

To define a call-by-value lambda, use lambda:

((lambda a b (+ a b)) 120 230)
; 120 + 230

((lambda a b (* a b)) 120 230)
; 120 * 230

((lambda a (+ a a)) 233)
; 466

Functions:

(def gcd a b (if (== 0 b) a (gcd b (% a b))))
(gcd 24 36)
; 12
  • Call by name (like C style macro, but not the same)

To define a call-by-name lambda, use expr:

(-> side-effect 10)
((expr used-twice
        (+ used-twice used-twice))
  (|> (-> side-effect (+ side-effect 1))
      233))

side-effect
; 12

Functions:

(defexpr f op (op true 1 2))
(f if)
; 1
  • Call by need(lazy evaluation)

To define a call-by-need to lambda, use lazy:

((lazy unused
       "any-val")
  (|> (def side-effect true)
      233))
(def? side-effect)
; false

Functions:

(deflazy unless condition a b (if condition b a))
(defexpr f op (op true 1 2))
(f unless)
; 2
  • Higher Order Functions

You can use lambda expressions everywhere, lambdas are first-class in Lice.

((lambda op (op 1 2 3)) +)

Built-in stuffs

  • List processing
(for-each i (.. 1 10) (print i))
; prints: from 1 to 10

(list "233" 1 3 "666")
; make a list

([|] 1 2 3 4)
; a pair: <1, <2, <3, <4, null>>>>
  • Metaprogramming
(def? if)
; true

(def? shit)
; false

(undef def?)
(def? if)
; error: `def?` undefined

(undef undef)
(undef whatever)
; error: `undef` undefined

(eval "(+ 1 1)")
; 2

LJI/Lice JVM Interface/Java API

  • Invoking Java
// java
public class Main {
	public static void main(String... args) {
		SymbolList sl = new SymbolList();
		sl.provideFunction(
				"java-api-invoking",
				ls -> 100 // ls is a list of Objects, cast them!
		);
		Lice.run(new File("sample/test10.lice"), sl);
	}
}
; Lice

(print (java-api-invoking))

Repl

Lice has a command line REPL, which will do completion, or list all the candidates when you press tab.

Here are some examples.

|> (+ 1 1)
2 => java.lang.Integer

|> ()
null => java.lang.Object

|> (eval "(+ 1 1)")
2 => java.lang.Integer
null => java.lang.Object

|> (eval (str-con "(+ " "1 " "1)"))
2 => java.lang.Integer
null => java.lang.Object

|> (cons 1 11 1)
[1, 11, 1] => java.util.ArrayList

|> (eval (read-file (file "sample/tests/test3.lice")))
16769025 => java.lang.Integer
My name is Van, I'm an artist => java.lang.String
My name is Van, I'm an artist => java.lang.String

|> (if (> 2 1) 1 2)
1 => java.lang.Integer

|> (-> file (file "fuck_you"))
fuck_you => java.io.File

|> (write-file file (str-con "deep" " dark fantasy"))
deep dark fantasy => java.lang.String

|> (read-file file)
deep dark fantasy => java.lang.String

|> ([|] 1 2 3 4 5)
[1 [2 [3 [4 [5 null]]]]] => org.lice.core.Pair

|> (-> i ([|] 1 2 3 4 5 6 7))
[1 [2 [3 [4 [5 [6 [7 null]]]]]]] => org.lice.core.Pair

|> (tail (tail i))
[3 [4 [5 [6 [7 null]]]]] => org.lice.core.Pair