1
0
mirror of https://github.com/janet-lang/janet synced 2024-12-27 17:00:27 +00:00

Update Intro.

Calvin Rose 2018-11-30 23:07:32 -05:00
parent 14a1cfc892
commit f310d478be

@ -74,7 +74,7 @@ notation with a radix besides 10, use the `&` symbol to indicate the exponent ra
Besides the 5 main arithmetic functions, janet also supports a number of math functions
taken from the C libary `<math.h>`, as well as bitwise operators that behave like they
do in C or Java. Functions like `math.sin`, `math.cos`, `math.log`, and `math.exp` will
do in C or Java. Functions like `math/sin`, `math/cos`, `math/log`, and `math/exp` will
behave as expected to a C programmer. They all take either 1 or 2 numeric arguments and
return a real number (never an integer!)
@ -161,7 +161,9 @@ created as needed.
Functions can be defined with the `defn` macro, like so:
```lisp
(defn triangle-area [base height]
(defn triangle-area
"Calculates the area of a triangle."
[base height]
(print "calculating area of a triangle...")
(* base height 0.5))
```
@ -197,12 +199,12 @@ literals without binding them to a symbol.
# Evaluates to 40
((fn [x y] (+ x x y)) 10 20)
# Also evaluates to 40
((fn @[x y] (+ x x y)) 10 20)
((fn [x y &] (+ x x y)) 10 20)
# Will throw an error about the wrong arity
((fn [x] x) 1 2)
# Will not throw an error about the wrong arity
((fn @[x] x) 1 2)
((fn [x &] x) 1 2)
```
The first expression creates an anonymous function that adds twice
@ -213,7 +215,7 @@ There is a common macro `defn` that can be used for creating functions and immed
them to a name. `defn` works as expected at both the top level and inside another form. There is also
the corresponding
Note that putting an ampersand in front of the argument list inhibits strict arity checking.
Note that putting an ampersand at the end of the argument list inhibits strict arity checking.
This means that such a function will accept fewer or more arguments than specified.
```lisp
@ -448,16 +450,16 @@ of the loop.
(-- i))
# Print ... until a random number in range [0, 1) is >= 0.9
# (math.random evaluates to a value between 0 and 1)
(while (> 0.9 (math.random))
# (math/random evaluates to a value between 0 and 1)
(while (> 0.9 (math/random))
(print "..."))
```
Besides these special forms, Janet has many macros for both conditional testing and looping
that are much better for the majority of cases. For conditional testing, the `cond`, `switch`, and
`when` macros can be used to great effect. `cond` can be used for making an if-else chain, where using
just raw if forms would result in many parentheses. `switch` For looping, the `loop` and `for` macro implement
list comprehension, as in Python, Clojure.
just raw if forms would result in many parentheses. `case` For looping, the `loop`, `seq`, and `generate`
implement janet's form of list comprehension, as in Python or Clojure.
# Combinators
@ -469,7 +471,7 @@ list comprehension, as in Python, Clojure.
# The Core Library
Janet has a built in core library of over 200 functions and macros at the time of writing.
Janet has a built in core library of over 300 functions and macros at the time of writing.
While some of these functions may be refactored into separate modules, it is useful to get to know
the core to avoid rewriting provided functions.
@ -481,7 +483,7 @@ For any given function, use the `doc` macro to view the documentation for it in
To see a list of all global functions in the repl, type the command
```lisp
(table.getproto *env*)
(table/getproto *env*)
# Or
(all-symbols)
```
@ -505,23 +507,19 @@ contents without duplicating memory.
```lisp
# One of many Object Oriented schemes that can
# be implented in janet.
(def proto1 @{:type :my.custom1
(def proto1 @{:type :custom1
:behave (fn [self x] (print "behaving " x))})
(def proto2 @{:type :my.custom2
(def proto2 @{:type :custom2
:behave (fn [self x] (print "behaving 2 " x))})
(def thing1 (table.setproto @{} proto1))
(def thing2 (table.setproto @{} proto2))
(def thing1 (table/setproto @{} proto1))
(def thing2 (table/setproto @{} proto2))
(print (get thing1 :type)) # prints :my.custom1
(print (get thing2 :type)) # prints :my.custom2
(print thing1:type) # prints :custom1
(print thing2:type) # prints :custom2
(defn behave [x y]
(let [{:behave f} x]
(f x y)))
(behave thing1 :a) # prints "behaving :a"
(behave thing2 :b) # prints "behaving 2 :b"
(thing1:behave thing1 :a) # prints "behaving :a"
(thing2:behave thing2 :b) # prints "behaving 2 :b"
```
Looking up in a table with a prototype can be summed up with the following algorithm.
@ -558,7 +556,7 @@ is used to differentiate different kinds of returns. When a fiber yields or thro
control is returned to the calling fiber. The parent fiber must then check what kind of state the
fiber is in to differentiate errors from return values from user defined signals.
To create a fiber, user the `fiber.new` function. The fiber constructor take one or two arguments.
To create a fiber, user the `fiber/new` function. The fiber constructor take one or two arguments.
the first, necessary argument is the function that the fiber will execute. This function must accept
an arity of one. The next optional argument is a collection of flags checking what kinds of
signals to trap and return via `resume`. This is useful so
@ -566,7 +564,7 @@ the programmer does not need to handle all different kinds of signals from a fib
are simply propagated to the next fiber.
```lisp
(def f (fiber.new (fn @[]
(def f (fiber/new (fn @[]
(yield 1)
(yield 2)
(yield 3)
@ -574,15 +572,15 @@ are simply propagated to the next fiber.
5)))
# Get the status of the fiber (:alive, :dead, :debug, :new, :pending, or :user0-:user9)
(print (fiber.status f)) # -> :new
(print (fiber/status f)) # -> :new
(print (resume f)) # -> prints 1
(print (resume f)) # -> prints 2
(print (resume f)) # -> prints 3
(print (resume f)) # -> prints 4
(print (fiber.status f)) # -> print :pending
(print (fiber/status f)) # -> print :pending
(print (resume f)) # -> prints 5
(print (fiber.status f)) # -> print :dead
(print (fiber/status f)) # -> print :dead
(print (resume f)) # -> throws an error because the fiber is dead
```
@ -599,7 +597,7 @@ Besides being used as coroutines, fibers can be used to implement error handling
# Use the :e flag to only trap errors.
(def f (fiber.new my-function-that-errors :e))
(def result (resume f))
(if (= (fiber.status f) :error)
(if (= (fiber/status f) :error)
(print "result contains the error")
(print "result contains the good result"))
```