According to http://www.phyast.pitt.edu/~micheles/scheme/scheme29.html
"It is worth mentioning that if you use a package system (like in Common Lisp) or a namespace system (like in Clojure) in practice variable capture becomes pretty rare. In Scheme instead, which uses a module system, hygiene is essential..."
What is the difference between a package system, a namespace system and a module system as the terms are used here?
Note that this is not about Lisp-1 versus Lisp-2 (which the linked document discusses separately). I'm guessing it might have something to do with the way, in Common Lisp, trying to use the same symbol in two different packages can get you two different symbols with the same name.
I think a common distinction between a package system and a module system is that a package system deals with mapping source text to names, while a module system deals with mapping names to meanings. (I don't know what a namespace system is, but I suspect it's a package system, perhaps without first-class packages, or even first-class names?)
In the context of Lisp, names are symbols, so a package system controls what symbol you get (specifically, what package it's in) when you read something which has the syntax of a symbol, while in a module system you always get the same symbol but its value depends on the module state.
Here's an example of how these things differ, using the CL package system and Racket's module system. Note that I'm a CL person: I understand the CL package system a lot better than I understand Racket's module system or Racket / Scheme macros.
Let's say I want to define some kind of symbolic algebra system and I'd like to be able to use syntax like (+ a b) when a and b may be things that cl:+ coes not understand, such as polynomials or something.
Well, I can do that in CL with a package definition something like this:
(defpackage :org.tfeb.symalg
(:use)
(:export "+" "-" "*" "/"))
(let ((p (find-package :org.tfeb.symalg)))
(do-external-symbols (s (find-package :cl))
(ecase (nth-value 1 (find-symbol (symbol-name s) p))
((nil)
(import s p)
(export s p))
((:external)
nil)
((:inherited :internal)
(error "package botch")))))
(defpackage :org.tfeb.symalg-user
(:use :org.tfeb.symalg))
(Note that, in real life, you'd obviously write a macro do do the above hair in a declarative & more flexible way: indeed some guy on the internet wrote a system called 'conduits' to do just this, and one day he'll probably get around to publishing it again.)
What this does is to create a package, org.tfeb.symalg which is like cl except that some specific symbols are different, and a package org.tfeb.symalg-user which uses this package instead of cl. In that package, (+ 1 2) means (org.tfeb.symalg:+ 1 2), but (car '(1 . 2)) means (cl:car '(1 . 2)).
But
(defmethod foo (a)
(:method-combination +))
also means
(defmethod foo (a)
(:method-combination org.tfeb.symalg:+))
and now I have some trouble: anywhere I wanted to use the symbol + as a symbol I have to type cl:+. (This specific example is easy to get around: I just need to define a method combination for org.tfeb.symalg:+, and I probably want to do that in any case, but there are other cases.)
This makes it a pain to do this sort of 'redefine bits of the language' thing in cases where I want to use names (symbols) which are part of the language as symbols.
Compare Racket: here is a little module definition in Racket which provides (or in fact doesn't) variant versions of some arithmetic symbols):
#lang racket
(provide
(rename-out
(plus +)
(minus -)
(times *)
(divide /)))
(define (plus . args)
(apply + args))
...
(define plus-symbol '+)
What this does is to say that, if you use this module, then the value of the symbol + is the value of the symbol plus in the module and so on. But the symbol is the same symbol. And you can easily check this if you are using the module by, for instance (eq? '+ plus-symbol), which will return #t: nothing funny is going on with what symbol you get when you type +, it's all in the mapping from those symbols to their values.
So this is much nicer: if Racket had a CLOS-style object system (and it probably has about six, some of which might half work), then the + method combination would just work, and in general anything which cares about symbols will work the way you want it to.
Except that one of the most common things you do in CL which manipulates symbols as symbols is macros. And if you try to take the CL approach to macros in Racket there is just hair everywhere.
In CL the approach is typically something like this:
The packages get defined somehow, and these definitions are the same throughout the compilation, loading and evaluation of the system.
Macros get defined.
The program is compiled with the macros being expanded.
The program is loaded and run.
And this all works fine: if my macro is defined in a situation where + means org.tfeb.symalg:+ then, if its expansion involves + it really involves org.tfeb.symalg:+, and so long at that package exists at compile time (which it will since compile time and macro expansion time are intertwined) and at run time and the definition is there then all will be well.
But it's not the same thing in Racket: if I write a macro then I know that the symbol + is just the symbol +. But what + means could be completely different at different times depending on the module state. And that could mean, for instance, that at compile time + meant Racket's native addition function, and so the compiler can optimise that into the ground, but perhaps at run time it means something else, because the module state is different now. The symbol + does not contain enough information to know what it should mean.
If you also take into account the information that Scheme people really care about sorting this sort of thing out in a clean way, and are definitely not happy with the CL approach to macros of 'stop thinking so hard & just use gensyms, it will all be fine', none of which is helped by Schemes being Lisp-1s, you can see that there are some fairly significant problems here which need to be addressed.
Common Lisp has a package system for symbols.
Notation:
cl-user::create ; symbol CREATE in package CL-USER
cl-user:create ; exported symbol CREATE in package CL-USER
create ; symbol CREATE in the - at read-time - current package
:create ; symbol CREATE in the package KEYWORD
#:create ; symbol CREATE, not in any package
Example in the Package CL-USER
Let's tell the reader that CL-USER is the current package:
(in-package "CL-USER")
A function CL-USER::CREATE
(defun create (x) ; CL-USER::CREATE
(list :list x))
A macro which creates code using above function
(defmacro m (x)
`(create ,x)) ; here we use CL-USER::CREATE
If we stay in this package, we can define a local function,
which will shadow the above global function.
(defun foo ()
(flet ((create (x) ; CL-USER::CREATE
(vector :vector x)))
(m (create 1)))) ; CL-USER::CREATE
So (m (create 1)) is (cl-user::create (cl-user::create 1)).
Both use the local function.
Example in the Package BAR
Now we can move our FOO function to another package BAR, which we will define here:
(defpackage "BAR"
(:use "COMMON-LISP")
(:export "FOO")
(:import-from "CL-USER" "M"))
Let's tell the reader to use this package BAR as the current package:
(in-package "BAR")
Now if we define our function FOO similar to above
(defun foo ()
(flet ((create (x) ; BAR::CREATE
(vector :vector x)))
(m (create 1)))) ; BAR::CREATE
So (m (create 1)) is (cl-user::create (bar::create 1)).
This means that the user code is not shadowing the function used by the macro.
But we can explicitly use the CL-USER::CREATE symbol:
(defun foo ()
(flet ((cl-user::create (x) ; CL-USER::CREATE
(vector :vector x)))
(m (cl-user::create 1)))) ; CL-USER::CREATE
So (m (create 1)) is (cl-user::create (cl-user::create 1)).
Using uninterned symbols
Common Lisp also provides symbols which are not interned in a package.
A special reader macro notation makes it possible to refer to such a symbol multiple
times in an expression: #1= is a marker and #1# references the marked object.
(defun foo ()
(flet ((#1=#:create (x) ; #:CREATE
(vector :vector x))) ;
(m (#1# 1)))) ; #:CREATE from above
So (m (#1# 1)) is (cl-user::create (#:create 1)),
where the `#:create symbol is the uninterned symbol referenced
from above.
Using computed symbols
Common Lisp also allows code to be run at read-time using the #. reader macro.
(defun foo ()
#.(let ((create-symbol (gensym "CREATE-")))
`(flet ((,create-symbol (x) ; #:CREATE-NNN
(vector :vector x)))
(m (,create-symbol 1))))) ; #:CREATE-NNN from above
Which might create code similar to this:
(DEFUN FOO ()
(FLET ((#:CREATE-815 (X) ; #:CREATE-815
(VECTOR :VECTOR X)))
(M (#:CREATE-815 1)))) ; #:CREATE-815 from above
So (m (#:CREATE-815 1)) is (cl-user::create (#:create-815 1)),
where the #:create-815 symbol is the symbol referenced
from above.
Related
Recently I came across a use for eval within a macro, which I understand is a bit of a faux pas but let's ignore that for now. What I found surprising, was that eval was able to resolve global vars at macroexpansion time. Below is a contrived example, just to illustrate the situation I'm referring to:
(def list-of-things (range 10))
(defmacro force-eval [args]
(apply + (eval args)))
(macroexpand-1 '(force-eval list-of-things))
; => 45
I would have expected args to resolve to the symbol list-of-things inside force-eval, and then list-of-things to be evaluated resulting in an error due to it being unbound:
"unable to resolve symbol list-of-things in this context"
However, instead list-of-things is resolved to (range 10) and no error is thrown - the macroexpansion succeeds.
Contrast this with attempting to perform the same macroexpansion, but within a local binding context:
(defmacro force-eval [args]
(apply + (eval args)))
(let [list-of-things (range 10)]
(macroexpand-1 '(force-eval list-of-things)))
; => Unable to resolve symbol: list-of-thingss in this context
Note in the above examples I'm assuming list-of-things is not previously bound, e.g. a fresh REPL. One final example illustrates why this is important:
(defmacro force-eval [args]
(apply + (eval args)))
(def list-of-things (range 10 20))
(let [list-of-thing (range 10)]
(macroexpand-1 '(force-eval list-of-things)))
; => 145
The above example shows that the locals are ignored, which is expected behavior for eval, but is a bit confusing when you are expecting the global to not be available at macroexpansion time either.
I seem to have a misunderstanding about what exactly is available at macroexpansion time. I had previously thought that essentially any binding, be it global or local, would not be available until runtime. Apparently this is an incorrect assumption. Is the answer to my confusion simply that global vars are available at macroexpansion time? Or am I missing some further nuance here?
Note: this related post closely describes a similar problem, but the focus there is more on how to avoid inappropriate use of eval. I'm mainly interested in understanding why eval works in the first example and by extension what's available to eval at macroexpansion time.
Of course, vars must be visible at compile time. That's where functions like first and + are stored. Without them, you couldn't do anything.
But keep in mind that you have to make sure to refer to them correctly. In the repl, *ns* will be bound, and so a reference to a symbol will look in the current namespace. If you are running a program through -main instead of the repl, *ns* will not be bound, and only properly qualified vars will be found. You can ensure that you qualify them correctly by using
`(force-eval list-of-things)
instead of
'(force-eval list-of-things)
Note I do not distinguish between global vars and non-global vars. All vars in Clojure are global. Local bindings are not called vars. They're called locals, or bindings, or variables, or some combination of those words.
Clojure is designed with an incremental compilation model. This is poorly documented.
In C and other traditional languages, source code must be compiled, then linked with pre-compiled libraries before the final result can be executed. Once execution begins, no changes to the code can occur until the program is terminated, when new source code can be compiled, linked, then executed. Java is normally used in this manner just like C.
With the Clojure REPL, you can start with zero source code in a live executing environment. You can call existing functions like (+ 2 3), or you can define new functions and variables on the fly (both global & local), and redefine existing functions. This is only possible because core Clojure is already available (i.e. clojure.core/+ etc is already "installed"), so you can combine these functions to define your own new functions.
The Clojure "compiler" works just like a giant REPL session. It reads and evaluates forms from your source code files one at a time, incrementally adding them the the global environment. Indeed, it is a design goal/requirement that the result of compiling and executing source code is identical to what would occur if you just pasted each entire source code file into the REPL (in proper dependency order).
Indeed, the simplest mental model for code execution in Clojure is to pretend it is an interpreter instead of a traditional compiler.
And eval in a macro makes no sense.
Because:
a macro already implicitely contains an eval
at the very final step.
If you use macroexpand-1, you make visible how the code was manipulated in the macro before the evocation of the implicite eval inside the macro.
An eval in a macro is an anti-pattern which might indicate that you should use a function instead of a macro - and in your examle this is exactly the case.
So your aim is to dynamically (in run-time) evoke sth in a macro. This you can only do through an eval applied over a macro call OR you should rather use a function.
(defmacro force-eval [args]
(apply + (eval args)))
;; What you actually mean is:
(defn force-eval [args]
(apply + args))
;; because a function in lisp evaluates its arguments
;; - before applying the function body.
;; That means: args in the function body is exactly
;; `(eval args)`!
(def list-of-things (range 10))
(let [lit-of-things (range 10 13)]
(force-eval list-of-things))
;; => 45
;; so this is exactly the behavior you wanted!
The point is, your construct is a "bad" example for a macro.
Because apply is a special function which allows you to
dynamically rearrange function call structures - so it has
some magic of macros inside it - but in run-time.
With apply you can do quite some meta programming in some cases when you just quote some of your input arguments.
(Try (force-eval '(1 2 3)) it returns 6. Because the (1 2 3) is put together with + at its front by apply and then evaluated.)
The second point - I am thinking of this answer I once gave and this to a dynamic macro call problem in Common Lisp.
In short: When you have to control two levels of evaluations inside a macro (often when you want a macro inject some code in runtime into some code), you need too use eval when calling the macro and evaluate those parts in the macro call which then should be processed in the macro.
I know in Scheme I can write this:
(let ((+ *)) (+ 2 3)) => 6
As well as this, in Clojure:
(let [+ *] (+ 2 3)) => 6
I know this can work, but it feels so weird. I think in any language, the math operators are predefined. C++ and Scala can do operator overloading, but this doesn't seem to be that.
Doesn't this cause confusion? Why does Lisp allow this?
This is not a general Lisp feature.
In Common Lisp the effects of binding a core language function is undefined. This means the developer should not expect that it works in portable code. An implementation may also signal a warning or an error.
For example the SBCL compiler will signal this error:
; caught ERROR:
; Lock on package COMMON-LISP violated when
; binding + as a local function while
; in package COMMON-LISP-USER.
; See also:
; The SBCL Manual, Node "Package Locks"
; The ANSI Standard, Section 11.1.2.1.2
; (DEFUN FOO (X Y)
; (FLET ((+ (X Y)
; (* X Y)))
; (+ X Y)))
We can have our own + in Common Lisp, but it then has to be in a different package (= symbol namespace):
(defpackage "MYLISP"
(:use "CL")
(:shadow CL:+))
(in-package "MYLISP")
(defun foo (a b)
(flet ((+ (x y)
(* x y)))
(+ a b)))
Disclaimer: This is from a Clojure point of view.
+ is just another function. You can pass it around and write sum with it, have partial application, read docs about it, ...:
user=> (apply + [1 2 3])
6
user=> (reduce + [1 2 3])
6
user=> (map (partial + 10) [1 2 3])
(11 12 13)
user=> `+
clojure.core/+
user=> (doc +)
-------------------------
clojure.core/+
([] [x] [x y] [x y & more])
Returns the sum of nums. (+) returns 0. Does not auto-promote
longs, will throw on overflow. See also: +'
So you can have many + in different namespaces. The core one get's "use"-ed for you by default, but you can simply write your own. You can write your own DSL:
user=> (defn + [s] (re-pattern (str s "+")))
WARNING: + already refers to: #'clojure.core/+ in namespace: user, being replaced by: #'user/+
#'user/+
user=> (+ "\\d")
#"\d+"
user=> (re-find (+ "\\d") "666")
"666"
It's not special form, it's nothing different from any other function. So with that established, why should it not be allowed to be overriden?
In Scheme you are making a local binding, shadowing whatever is higher, With let. Since + and * are just variables that just happen to evaluate to procedures you are just giving old procedures other variable names.
(let ((+ *))
+)
; ==> #<procedure:*> (non standard visualization of a procedure)
In Scheme there are no reserved words. If you look at other languages the list of reserved words are quite high. Thus in Scheme you can do this:
(define (test v)
(define let 10) ; from here you cannot use let in this scope
(define define (+ let v)) ; from here you cannot use define to define stuff
define) ; this is the variable, not the special form
;; here let and define goes out of scope and the special forms are OK again
(define define +) ; from here you cannot use top level define
(define 5 6)
; ==> 11
THe really nice thing about this is that if you choose a name and the next version of the standard happens to use the same name for something similar, but not compatible, your code will not break. In other languages I have worked with a new version might introduce conflicts.
R6RS makes it even easier
From R6RS we have libraries. That means that we have full control over what top level forms we get from the standard into our programs. You have several ways to do it:
#!r6rs
(import (rename (except (rnrs base) +) (* +)))
(+ 10 20)
; ==> 200
This is also OK.
#!r6rs
(import (except (rnrs base) +))
(define + *)
(+ 10 20)
; ==> 200 guaranteed
And finally:
#!r6rs
(import (rnrs base)) ; imports both * and +
(define + *) ; defines + as an alias to *
(+ 10 20)
; ==> 200 guaranteed
Other languages does this too:
JavaScript is perhaps the most obvious:
parseFloat = parseInt;
parseFloat("4.5")
// ==> 4
But you cannot touch their operators. They are reserved because the language needs to do a lot of stuff for the operator precedence. Just like Scheme JS is nice language for duck typing.
Mainstream Lisp dialects do not have reserved tokens for infix operations. There is no categorical difference between +, expt, format or open-file: they are all just symbols.
A Lisp proram which performs (let ((+ 3)) ...) is spiritually very similar to a C program which does something like { int sqrt = 42; ... }. There is a sqrt function in the standard C library, and since C has a single namespace (it's a Lisp-1), that sqrt is now shadowed.
What we can't do in C is { int + = 42; ...} which is because + is an operator token. An identifier is called for, so there is a syntax error. We also can't do { struct interface *if = get_interface(...); } because if is a reserved keyword and not an identifier, even though it looks like one. Lisps tend not to have reserved keywords, but some dialects have certain symbols or categories of symbols that can't be bound as variables. In ANSI Common Lisp, we can't use nil or t as variables. (Specifically, those symbols nil and t that come from the common-lisp package). This annoys some programmers, because they'd like a t variable for "time" or "type". Also, symbols from the keyword package, usually appearing with a leading colon, cannot be bound as variables. The reason is that all these symbols are self-evaluating. nil, t and the keyword symbols evaluate to themselves, and so do not act as variables to denote another value.
The reason we allow this in lisp is that all bindings are done with lexical scope, which is a concept that comes from lambda calculus.
lambda calculus is a simplified system for managing variable binding. In lambda calculus the rules for things like
(lambda (x) (lambda (y) y))
and
(lambda (x) (lambda (y) x))
and even
(lambda (x) (lambda (x) x))
are carefully specified.
In lisp LET can be thought of as syntactic sugar for a lambda expression, for example your expression (let ([+ x]) (+ 2 3)) is equivalent to ((lambda (+) (+ 2 3)) x) which according to lambda calculus simplifies down to (x 2 3).
In summary, lisp is based on uniformly applying a very simple and clear model (called lambda calculus). If it seems strange at first, that's because most other programming languages don't have such consistency or base their variable binding on a mathematical model.
Scheme's philosophy is to impose minimal restriction such that to give maximal power to programmer.
A reason to allow such things is that in Scheme you can embed other languages and in other languages you want to use the * operator with different semantics.
For example, if you implement a language to represent regular expressions you want to give the * the semantics of the algebraic kleene operator and write programs like this one
(* (+ "abc" "def") )
to represent a language that contain words like this one
empty
abc
abcabc
abcdef
def
defdef
defabc
....
Starting from the main language, untyped lambda calculus, it is possible to create a language in which you can redefine absolutely everything apart from the lambda symbol. This is the model of computation scheme is build on.
It's not weird because in lisp there are no operators except functions and special forms like let or if, that can be builtin or created as macros. So here + is not an operator, but a function that is assigned to symbol + that is adding its arguments (in scheme and clojure you can say that it's just variable that hold function for adding numbers), the same * is not multiplication operator but asterisk symbol that is multiplying its arguments, so this is just convenient notation that it use + symbol it could be add or sum but + is shorter and similar as in other languages.
This is one of this mind bending concepts when you found it for the first time, like functions as arguments and return values of other functions.
If you use very basic Lisp and lambda calculus you don't even need numbers and + operators in base language. You can create numbers from functions and plus and minus functions using same trick and assign them to symbols + and - (see Church encoding)
Why does Lisp allow rebinding of math operators?
for consistency and
because it can be useful.
Doesn't this cause confusion?
No.
Most programming languages, following traditional algebraic notation, have special syntax for the elementary arithmetic functions of addition and subtraction and so on. Rules of priority and association make some function calls implicit. This syntax makes the expressions easier to read at the price of consistency.
LISPs tip the see-saw the other way, preferring consistency over legibility.
Consistency
In Clojure (the Lisp I know), the math operators (+, -, *, ... ) are nothing special.
Their names are just ordinary symbols.
They are core functions like any others.
So of course you can replace them.
Usefulness
Why would you want to override the core arithmetic operators? For example, the units2 library redefines them to accept dimensioned quantities as well as plain numbers.
Clojure algebra is harder to read.
All operators are prefix.
All operator applications are explicit - no priorities.
If you are determined to have infix operators with priorities, you can do it. Incanter does so: here are some examples and here is the source code.
As I read blog Revenge of the nerds, It says (in what made Lisp different section):
The whole language there all the time. There is no real distinction between read-time, compile-time, and runtime. You can compile or run code while reading, read or run code while compiling, and read or compile code at runtime.
Running code at read-time lets users reprogram Lisp's syntax; running code at compile-time is the basis of macros; compiling at runtime is the basis of Lisp's use as an extension language in programs like Emacs; and reading at runtime enables programs to communicate using s-expressions, an idea recently reinvented as XML.
In order to understand this sentence, I draw a statechart diagram:
I have two questions:
how to understand to read at runtime enable programming to communicate using s-expression, an idea reinvented as XML
what can we do when compiling at read time or reading at compile time?
XML let you exchange data at runtime between programs (or between different invocations of the same program). The same goes for JSON, which is a subset of Javascript and a little closer to Lisp in spirit. However, Common Lisp gives more control over how the different steps are executed; as explained in the quotes, you can reuse the same tools as your Lisp environment instead of building a framework like other languages need to.
Basically, you print data to a file:
(with-open-file (out file :direction :output)
(write data :stream out :readably t))
... and you restore it later :
(with-open-file (in file) (read in))
You call that "serialization" or "marshalling" in other languages (and in fact, in some Lisp libraries).
The READ step can be customized: you can read data written in a custom syntax (JSON.parse accepts a reviver function, so it is a little bit similar; the Lisp reader works for normal code too). For example, the local-time library has a special syntax for dates that can be used to rebuild a date object from a stream.
In practice, this is a bit more complex because not all data has a simple readable form (how do you save a network connection?), but you can write forms that can restore the information when you load it (e.g. restore a connection). So Lisp allows you to customize READ and PRINT, with readtables and PRINT-OBJECT, but there is also LOAD-TIME-VALUE and MAKE-LOAD-FORM, which allows you to allocate objects and initialize them when loading code. All of this is already available in the language, but there are also libraries that make things even easier, like cl-conspack: you just store classes into files and load them back without having to define anything special (assuming you save all slots). This works well thanks to the meta-object protocol.
Common Lisp
READ is a function which reads s-expressions and returns Lisp data.
CL-USER> (read)
(defun example (n) (if (zerop n) 1 (* (example (1- n)) n))) ; <- input
(DEFUN EXAMPLE (N) (IF (ZEROP N) 1 (* (EXAMPLE (1- N)) N))) ; <- output
The last result again:
CL-USER> *
(DEFUN EXAMPLE (N) (IF (ZEROP N) 1 (* (EXAMPLE (1- N)) N)))
Setting the variable code to the last result.
CL-USER> (setf code *)
(DEFUN EXAMPLE (N) (IF (ZEROP N) 1 (* (EXAMPLE (1- N)) N)))
What is the third element?
CL-USER> (third code)
(N)
We can evaluate this list, since it looks like valid Lisp code:
CL-USER> (eval code)
EXAMPLE
The function EXAMPLE has been defined. Let's get the function object:
CL-USER> (function example)
#<interpreted function EXAMPLE 21ADA5B2>
It's an interpreted function. We use a Lisp interpreter.
Let's use the function by mapping it over a list:
CL-USER> (mapcar (function example) '(1 2 3 4 5))
(1 2 6 24 120)
Let's compile the function:
CL-USER> (compile 'example)
EXAMPLE
NIL
NIL
The function has been compiled successfully. The compiler has no warnings and the function should now run much faster.
Let's use it again:
CL-USER> (mapcar (function example) '(1 2 3 4 5))
(1 2 6 24 120)
This is the same result, but probably much faster computed.
Since it is now compiled, let's disassemble the function:
CL-USER> (disassemble #'example)
0 : #xE3E06A03 : mvn tmp1, #12288
4 : #xE18D6626 : orr tmp1, sp, tmp1, lsr #12
8 : #xE5166030 : ldr tmp1, [tmp1, #-48]
... and a lot more lines of ARM assembler machine code
The code below prints 10 as expected.
(def x 10)
(let [y 30] (eval (symbol "x")))
The code below generates an exception:
(let [y 20] (eval (symbol "y")))
Unable to resolve symbol: y in this context
which is expected (but confusing!). According to the documentation, symbols defined by let do not belong to any namespace and so can not be resolved through namespace mechanism.
So the question is: what should be an equivalent of function symbol for local variables.
Additionally:
I thought that Clojure compiler internally calls function symbol for each identifier to "intern" it, but as the example above shows it is not the case. Curious what the compiler is actually doing with the local identifiers. I assumed that when I enter x in REPL
x
is is essentially processed as this:
(deref (resolve (symbol "x")))
but again evidently it is not the case for local variables.
PS: Symbols in Clojure does not cover local variables.
All input to the clojure compiler is read, to form lists, symbols, keywords, numbers, and other readable data (eg. if you use a hash map literal, the compiler will get a hash map).
For example:
user=> (eval '(let [y 20] y))
20
In this case, we give the compiler a list starting with the symbol let (which resolves to a var macro wrapping a special form).
When you ask "what should be an equivalent of function symbol for local variables", my first thought is that you are misunderstanding what the function symbol is for. The following is equivalent to my initial example:
user=> (eval (list (symbol "let") [(symbol "y") 20] (symbol "y")))
20
symbol is only incidentally useful for getting a var from a string. In fact this usage is usually a hack, and a sign you are doing something wrong. Its primary purpose is to construct input for the compiler. Writing a form that gets a binding from its lexical scope is best done by writing a function, and having the user pass in the value to be used. History shows us that implicitly using locals in the callers environment is messy and error prone, and it is not a feature that Clojure explicitly supports (though there are definitely hacks that will work, which will be based on implementation details that are not guaranteed to behave properly the next release of the language).
In my list, addition, the operation + appears as #. How can I make this appear exactly as +? When I eval it, it should also work exactly the same as +.
I guess this would also apply in all kinds of functions in Clojure...
Thanks guys.
The # character is simply not a valid character in symbol names in Clojure (see this page for a list of valid characters) and while it might work sometimes (as it often will), it is not a good practice to use it. Also, it will definitely not work at the beginning of a symbol (actually a literal, you could still do (symbol "#"), though there's probably no point in that). As the Clojure reader currently stands, there's nothing to be done about it (except possibly hacking the reader open to have it treat # (that's '#' followed by a space) as the symbol # -- or simply + -- though that's something you really shouldn't do, so I almost feel guilty for providing a link to instructions on how to do it).
Should you want to alias a name to some other name which is legal in Clojure, you may find it convenient to use the clojure.contrib.def/defalias macro instead of plain def; this has the added benefit of setting metadata for you (and should handle macros, though it appears to have a bug which prevents that at this time, at least in 1.2 HEAD).
And in case you'd like to redefine some built-in names when creating your aliases... (If you don't, the rest of this may not be relevant to you.)
Firstly, if you work with Clojure 1.1 or earlier and you want to provide your own binding for a name from clojure.core, you'll need to use :refer-clojure when defining your namespace. E.g. if you want to provide your own +:
(ns foo.bar
(:refer-clojure :exclude [+]))
;; you can now define your own +
(defn + [x y]
(if (zero? y)
x
(recur (inc x) (dec y))))
;; examples
(+ 3 5)
; => 8
(+ 3 -1)
; => infinite loop
(clojure.core/+ 3 -1)
; => 2
The need for this results from Clojure 1.1 prohibiting rebinding of names which refer to Vars in other namespaces; ns-unmap provides a way around it appropriate for REPL use, whereas (:refer-clojure :exclude ...), (:use :exclude ...) and (:use :only ...) provide the means systematically to prevent unwanted names from being imported from other namespaces in the first place.
In current 1.2 snapshots there's a "last-var-in wins" policy, so you could do without the :refer-clojure; it still generates a compiler warning, though, and it's better style to use :refer-clojure, plus there's no guarantee that this policy will survive in the actual 1.2 release.
An operation is just a piece of code, assigned to a variable. If you want to rebind an operation, you just rebind that variable:
(def - +)
(- 1 2 3)
# => 6
The only problem here, is that the # character is special in Clojure. I'm not sure whether you can use # as a variable name at all, at the very least you will need to quote it when binding it and probably also when calling it:
(def # +)
# => java.lang.Exception: No dispatch macro for:
Unfortunately, I'm not familiar enough with Clojure to know how to quote it.