Hi Andreas >no need to be sorry, we like to help That's very kind of you. Thank you and your message looks very helpful indeed. It'll take me a while to digest it but I will come back re it. For now...most of my programming has been in Powerbasic though I have done some C++, Perl and Tcl so...yes {} == scoping to me.
Best Regards Dean On 9 December 2016 at 23:27, <andr...@itship.ch> wrote: > Hi dean > > No worries, no need to be sorry, we like to help :-) > Here a more lengthy and maybe easier explanation, though not simpler... > Feedback appreciated. > > >From which languages are you coming from? > It looks to me like you view lisp brackets ( ) similar to curly brackets { > } in C/C++/C#/Java/..., where { } is doing scoping. > While they appear similar at first, they don't really have much in common. > Brackets in lisp are also used for grouping and nesting, but on a much more > basic level. > > Lets leave brackets aside first and have a look at the basic types of > picolisp. When you grokked this, you will grok brackets. > Picolisp has three strongly typed types: > > 1) Number - represent a signed integral (integer) value of arbitrary size > In text form (as in source code) they are just plain written as numbers: > 123 > Whenever there is a number within picolisp source code (without any > "quotes" around it), its automatically detected as a numeric integer value. > > 2) Symbol - has a value, and optionally a name and an arbitrary number of > properties (also might have none) > If you're new to lisp, coming from a C-style language, then this is > probably the weirdest and most complex data type to understand. > At minimum a symbol has a value, but the value can be anything - maybe it > helps to think of it as a reference/pointer to some other value, e.g. a > number, another symbol, or a list. > Most times, a symbol has also a name - think of it like the name of a > variable in other languages. > Additionally a symbol can have none, one or multiple properties - which > again consists of a name and a value. > (This makes symbols looking a bit like OOP classes in other languages, but > the symbol type alone is not really a class or object, though the picolisp > OOP classes are based on symbols). > > Symbol is a very powerful and wildly diversely used type. > And there are actually kind of 4 different (sub-)types of symbols, which > differ a bit in behaviour and usage context, but the description above is > true for all of them. > > Whenever there is a string within picolisp source code (without any > "quotes" around it), its automatically detected as a symbol. > strings with "quotes" around it are actually also symbols, in picolisp we > call them "transient symbols" because they live in a transient scope, what > this means exactly you can look up later on, for the moment think of them > as a symbol used to represent a character string. > > ATOMS: The Number and Symbol types are called atoms, because they don't > consist of other types. > Check out the function (atom): http://software-lab.de/doc/refA.html#atom > > So, now we have 2 of the 3 picolisp base data types. Now lets look at the > third data type, the one which is not an atom. > > 3) List - a sequence of one or more cells (cons pairs), holding numbers, > symbols, or cons pairs. > Simply said, a list is a grouping of values, wherein each value can be a > number, a symbol, or also another list. > > In the picolisp source code, a list is surrounded by ( ) brackets (lisp > users usually call them parens, not brackets, I guess this is short for > parenthesis). > Technically every ( ) in the picolisp source code denotes a list, but > attention: not every ( ) in the code results in a list variable. Just keep > carry on, you will understand the meaning of this when you finished the > next section about evaluation below... > > Two parens in source code, which only contain one or multiple Numbers, is > automatically detected as a list value: (1 2 3 55) > A list value which contains other stuff, needs to be prefixed with ' (this > is the quote-macro of picolisp): (symbol 2 3 this is a list) <- yep, this > is a list containing the Numbers 2 and 3, and the Symbols "symbol", "this", > "is", "a" and "list" > > This are the three basic types of picolisp. Everything else in picolisp is > made up from those types! Everything! > (and those are made up of cells, a cell is basically a single piece of > memory in picolisp runtime). > > EVALUATION > This is the other fundamental topic to understand, evaluation, turning > input into output, the essence of software. > Evaluation is a big topic in other programming languages too, but maybe > the exact process is a bit more hidden and implicit than in lisp languages. > REPL stands for READ - EVALUATE - PRINT -LOOP, and this is exactly what > the picolisp runtime does. > 1) read the source code -> build a structure in memory which is an exact > binary representation of the textual representation of the program, which > is the source code. > 2) evaluate -> turning input into output according to a certain set of > rules > 3) print -> print the result on the screen (or maybe not, for example: a > pure server program talking over a network connection to a client program) > 4) loop -> repeat again with step 1), until the program is exited by > calling (bye) or is shut down by the OS > > When you start picolisp without any arguments (invoking pil or pil +), you > end up in the REPL. > When you enter something and press return, the steps of the REPL are > followed through. > > Values of type Number are always evaluated as themselves, meaning 123 -> > returns 123. > Symbols return their value, or return the special Symbol NIL if they don't > have a value: > : A -> NIL > : (setq A 123) > : A -> 123 > > Transient symbols, the special case of symbols with "quotes" around them, > return their name, unless they have a value: > : "Switzerland" -> "Switzerland" > : (setq "Switzerland" "Schweiz") # set value of Symbol "Switzerland" to > the german word > : "Switzerland" -> "Schweiz" > > And now comes the magic... > > Lists in source code, so everything with parens (around it), are evaluated > as function calls! > Because functions are represented as list data type... > > Examples: > (print "Schwitzerland") -> this means: call the function print and give > it, as an argument, whatever "Switzerland" evaluates to (so this could be > "Switzerland" or "Schweiz", see the evaluation of transient symbols as > explained just above) > (if (= 1 1) "true" "false") -> this means: call the function if and give > it, as arguments, this other elements contained in this list > > Normally, all arguments to a function are evaluated before executing the > function! > Some functions are special (so called fexpr, short for f-expressions, > historically for "user defined special form") > The function if behaves like a fexpr (albeit to be exact, its not user > defined but hardcoded in picolisp runtime) > > if: > evaluate the first argument, > if its non-NIL, evaluate and return the second argument, > otherwise (if the second argument evaluated to NIL) evaluate all other > arguments (except the second argument) and return the result of the > evaluation of the last argument > > Step by step: > 1) (if (= 1 2) "true" (prinl "bla") "false") -> oh we should evaluate the > first argument, to find out what we need to do > 2) (if NIL "true" (prinl "bla") "false") -> well, (= 1 2) evaluates to the > Symbol NIL, so lets skip the evaluation of the second argument and evaluate > all others > 3) (prinl "bla") -> oh, a nested evaluation, ok lets evaluate the > transient Symbol "bla", which results in "bla", and execute prinl on that > value > 4) ok, back in the if, what next? -> evaluate "false" -> easy, result is > "false" -> ok, this was the last argument to if, lets return this value -> > "false" > > Lets see how a function is defined/created: > (de hello-world () > (prinl "hi world") ) > > Ha, this is again a list in the source code! Containing the symbol "de", > the symbol "hello-world", an empty list (empty lists evaluate to NIL), and > another list. > How is this evaluated? As a call to the built-in function "de", which is > also kinda a fexpr, taking all its argument as input without evaluation. > "de" then creates a new symbol with the name "hello-world" and the value > as a list which looks like this: (() (prinl "hi world")) -> so the value is > a list which contains an empty list plus a list with two symbols in it